bug 448989. Merging the mozilla-qt repository. r=me,vlad
authorStuart Parmenter <pavlov@pavlov.net>
Sat, 16 Aug 2008 23:18:27 -0700
changeset 16964 4a506fa751d8
parent 16756 4e27fb8bb3e5 (current diff)
parent 16963 9095dca03bd2 (diff)
child 16965 6cd9fb678292
push id1298
push userpavlov@mozilla.com
push date2008-08-17 05:03 +0000
treeherdermozilla-central@4a506fa751d8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme, vlad
bugs448989
milestone1.9.1a2pre
bug 448989. Merging the mozilla-qt repository. r=me,vlad
gfx/thebes/src/gfxPlatform.cpp
js/src/jsstr.cpp
layout/build/Makefile.in
toolkit/xre/nsAppRunner.cpp
--- a/browser/themes/Makefile.in
+++ b/browser/themes/Makefile.in
@@ -50,13 +50,13 @@ include $(DEPTH)/config/autoconf.mk
 # MacOS X                 Pinstripe
 #
 
 ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
 DIRS = pinstripe
 else
 DIRS = winstripe
 endif
-ifneq (,$(filter gtk2,$(MOZ_WIDGET_TOOLKIT)))
+ifneq (,$(filter gtk2 qt,$(MOZ_WIDGET_TOOLKIT)))
 DIRS = gnomestripe
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/client.mk
+++ b/client.mk
@@ -88,17 +88,17 @@ ifeq (,$(wildcard client.mk))
 $(error Must run from the client.mk directory, or specify TOPSRCDIR)
 endif
 TOPSRCDIR = $(CWD)
 endif
 
 ifeq (Darwin,$(shell uname -s))
 AUTOCONF ?= autoconf213
 else
-AUTOCONF ?= autoconf-2.13
+AUTOCONF ?= $(shell which autoconf-2.13 autoconf2.13 autoconf213 | head -1)
 endif
 
 MKDIR := mkdir
 SH := /bin/sh
 ifndef MAKE
 MAKE := gmake
 endif
 PERL ?= perl
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -168,16 +168,17 @@ MOZ_MORKREADER = @MOZ_MORKREADER@
 MOZ_NO_XPCOM_OBSOLETE = @MOZ_NO_XPCOM_OBSOLETE@
 MOZ_NO_FAST_LOAD = @MOZ_NO_FAST_LOAD@
 MOZ_OGG = @MOZ_OGG@
 MOZ_MEDIA = @MOZ_MEDIA@
 NS_PRINTING = @NS_PRINTING@
 MOZ_CRASHREPORTER = @MOZ_CRASHREPORTER@
 MOZ_MOCHITEST = @MOZ_MOCHITEST@
 MOZ_HELP_VIEWER = @MOZ_HELP_VIEWER@
+MOC= @MOC@
 
 MOZ_JAVAXPCOM = @MOZ_JAVAXPCOM@
 JAVA_INCLUDE_PATH="@JAVA_INCLUDE_PATH@"
 JAVA="@JAVA@"
 JAVAC="@JAVAC@"
 JAR="@JAR@"
 
 TAR=@TAR@
@@ -492,34 +493,39 @@ MKCSHLIB                = @MKCSHLIB@
 MKSHLIB_FORCE_ALL       = @MKSHLIB_FORCE_ALL@
 MKSHLIB_UNFORCE_ALL     = @MKSHLIB_UNFORCE_ALL@
 DSO_LDOPTS              = @DSO_LDOPTS@
 DLL_SUFFIX              = @DLL_SUFFIX@
 
 NO_LD_ARCHIVE_FLAGS     = @NO_LD_ARCHIVE_FLAGS@
 
 GTK_CONFIG	= @GTK_CONFIG@
+QT_CONFIG	= @QT_CONFIG@
 TK_CFLAGS	= @TK_CFLAGS@
 TK_LIBS		= @TK_LIBS@
 
 MOZ_TOOLKIT_REGISTRY_CFLAGS = \
 	$(TK_CFLAGS)
 
 CAIRO_FT_CFLAGS		= @CAIRO_FT_CFLAGS@
 
 MOZ_ENABLE_CAIRO_FT	= @MOZ_ENABLE_CAIRO_FT@
 MOZ_ENABLE_GLITZ        = @MOZ_ENABLE_GLITZ@
 MOZ_ENABLE_GTK2		= @MOZ_ENABLE_GTK2@
+MOZ_ENABLE_QT		= @MOZ_ENABLE_QT@
 MOZ_ENABLE_PHOTON	= @MOZ_ENABLE_PHOTON@
 MOZ_ENABLE_COCOA	= @MOZ_ENABLE_COCOA@
 MOZ_ENABLE_XREMOTE	= @MOZ_ENABLE_XREMOTE@
 
 MOZ_GTK2_CFLAGS		= @MOZ_GTK2_CFLAGS@
 MOZ_GTK2_LIBS		= @MOZ_GTK2_LIBS@
 
+MOZ_QT_CFLAGS		= @MOZ_QT_CFLAGS@
+MOZ_QT_LIBS		= @MOZ_QT_LIBS@
+
 MOZ_DBUS_GLIB_CFLAGS    = @MOZ_DBUS_GLIB_CFLAGS@
 MOZ_DBUS_GLIB_LIBS      = @MOZ_DBUS_GLIB_LIBS@
 MOZ_ENABLE_DBUS         = @MOZ_ENABLE_DBUS@
 
 MOZ_GTHREAD_CFLAGS      = @MOZ_GTHREAD_CFLAGS@
 MOZ_GTHREAD_LIBS        = @MOZ_GTHREAD_LIBS@
 
 FT2_CFLAGS             = @FT2_CFLAGS@
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -316,16 +316,20 @@ ALL_TRASH = \
 	$(SHARED_LIBRARY:$(DLL_SUFFIX)=.exp) $(wildcard *.ilk) \
 	$(PROGRAM:$(BIN_SUFFIX)=.exp) $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=.exp) \
 	$(PROGRAM:$(BIN_SUFFIX)=.lib) $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=.lib) \
 	$(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=.$(OBJ_SUFFIX)) \
 	$(wildcard gts_tmp_*) $(LIBRARY:%.a=.%.timestamp)
 ALL_TRASH_DIRS = \
 	$(GARBAGE_DIRS) /no-such-file
 
+ifdef QTDIR
+GARBAGE                 += $(MOCSRCS)
+endif
+
 ifdef SIMPLE_PROGRAMS
 GARBAGE			+= $(SIMPLE_PROGRAMS:%=%.$(OBJ_SUFFIX))
 endif
 
 ifdef HOST_SIMPLE_PROGRAMS
 GARBAGE			+= $(HOST_SIMPLE_PROGRAMS:%=%.$(OBJ_SUFFIX))
 endif
 
--- a/configure.in
+++ b/configure.in
@@ -4687,25 +4687,27 @@ MOZ_ARG_HEADER(Toolkit Options)
                           Platform specific defaults:
                             BeOS - cairo-beos
                             Mac OS X - cairo-cocoa
                             Neutrino/QNX - photon
                             OS/2 - cairo-os2
                             Win32 - cairo-windows
                             WinCE - windows
                             Gtk2 with DirectFB - cairo-gtk2-dfb
-                            * - cairo-gtk2],
+                            * - cairo-gtk2
+                            * - cairo-qt],
     [ _DEFAULT_TOOLKIT=$enableval ],
     [ _DEFAULT_TOOLKIT=$_PLATFORM_DEFAULT_TOOLKIT])
 
     if test "$_DEFAULT_TOOLKIT" = "photon" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-windows" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-gtk2" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-gtk2-dfb" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-gtk2-x11" \
+        -o "$_DEFAULT_TOOLKIT" = "cairo-qt" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-beos" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-os2" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-mac" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-cocoa"
     then
         dnl nglayout only supports building with one toolkit,
         dnl so ignore everything after the first comma (",").
         MOZ_WIDGET_TOOLKIT=`echo "$_DEFAULT_TOOLKIT" | sed -e "s/,.*$//"`
@@ -4756,16 +4758,30 @@ cairo-gtk2-dfb)
     TK_LIBS='$(MOZ_GTK2_LIBS)'
     AC_DEFINE(MOZ_WIDGET_GTK2)
     if test "$no_x" != "yes"; then
         AC_MSG_WARN([Disabling X when DirectFB is specified.])
         no_x=yes
     fi
     ;;
 
+cairo-qt)
+    MOZ_WIDGET_TOOLKIT=qt
+    MOZ_GFX_TOOLKIT=cairo
+    MOZ_ENABLE_QT=1
+    MOZ_ENABLE_XREMOTE=1
+
+    AC_DEFINE(MOZ_X11)
+    MOZ_X11=1
+
+    TK_CFLAGS='$(MOZ_QT_CFLAGS)'
+    TK_LIBS='$(MOZ_QT_LIBS)'
+    AC_DEFINE(MOZ_WIDGET_QT)
+    ;;
+
 cairo-beos)
     MOZ_WIDGET_TOOLKIT=beos
     MOZ_GFX_TOOLKIT=cairo
     TK_CFLAGS='$(MOZ_CAIRO_CFLAGS)'
     TK_LIBS='$(MOZ_CAIRO_LIBS)'
     ;;
 
 cairo-os2)
@@ -4845,27 +4861,69 @@ then
     fi
 
     TK_LIBS="$TK_LIBS $MOZ_STARTUP_NOTIFICATION_LIBS"
 fi
 AC_SUBST(MOZ_ENABLE_STARTUP_NOTIFICATION)
 AC_SUBST(MOZ_STARTUP_NOTIFICATION_CFLAGS)
 AC_SUBST(MOZ_STARTUP_NOTIFICATION_LIBS)
 
+dnl ========================================================
+dnl = QT support
+dnl ========================================================
+if test "$MOZ_ENABLE_QT"
+then
+    PKG_CHECK_MODULES(MOZ_QT, QtGui QtNetwork QtUiTools QtCore)
+    AC_SUBST(MOZ_QT_CFLAGS)
+    AC_SUBST(MOZ_QT_LIBS)
+
+    MOZ_ARG_WITH_STRING(qtdir,
+    [  --with-qtdir=\$dir       Specify Qt directory ],
+    [ QTDIR=$withval])
+
+    if test -z "$QTDIR"; then
+      QTDIR="/usr"
+    fi
+    QTINCDIR="/include/qt"
+    if test ! -d "$QTDIR$QTINCDIR"; then
+       QTINCDIR="/include/X11/qt"
+    fi
+    if test ! -d "$QTDIR$QTINCDIR"; then
+       QTINCDIR="/include"
+    fi
+
+    if test -x "$QTDIR/bin/moc-qt4"; then
+      HOST_MOC="$QTDIR/bin/moc-qt4"
+    else
+      if test -x "$QTDIR/bin/moc"; then
+        HOST_MOC="$QTDIR/bin/moc"
+      else
+        AC_CHECK_PROGS(HOST_MOC, moc, "")
+      fi
+    fi
+    if test -z "$HOST_MOC"; then
+      AC_MSG_ERROR([no acceptable moc preprocessor found])
+    fi
+    MOC=$HOST_MOC
+fi
+
 AC_SUBST(GTK_CONFIG)
 AC_SUBST(TK_CFLAGS)
 AC_SUBST(TK_LIBS)
 
 AC_SUBST(MOZ_ENABLE_GTK2)
 AC_SUBST(MOZ_ENABLE_PHOTON)
 AC_SUBST(MOZ_ENABLE_COCOA)
 AC_SUBST(MOZ_ENABLE_GLITZ)
+AC_SUBST(MOZ_ENABLE_QT)
 AC_SUBST(MOZ_ENABLE_XREMOTE)
 AC_SUBST(MOZ_GTK2_CFLAGS)
 AC_SUBST(MOZ_GTK2_LIBS)
+AC_SUBST(MOZ_QT_CFLAGS)
+AC_SUBST(MOZ_QT_LIBS)
 
 AC_SUBST(MOC)
 
 AC_SUBST(MOZ_DFB)
 AC_SUBST(MOZ_X11)
 
 dnl ========================================================
 dnl =
@@ -7452,16 +7510,19 @@ if test "$MOZ_TREE_CAIRO"; then
         XLIB_SURFACE_FEATURE="#define CAIRO_HAS_XLIB_SURFACE 1"
         XLIB_XRENDER_SURFACE_FEATURE="#define CAIRO_HAS_XLIB_XRENDER_SURFACE 1"
         PS_SURFACE_FEATURE="#define CAIRO_HAS_PS_SURFACE 1"
         PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
         FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
         MOZ_ENABLE_CAIRO_FT=1
         CAIRO_FT_CFLAGS="$FT2_CFLAGS"
     fi
+    if test "$MOZ_WIDGET_TOOLKIT" = "qt"; then
+        QPAINTER_SURFACE_FEATURE="#define CAIRO_HAS_QPAINTER_SURFACE 1"
+    fi
     if test "$MOZ_WIDGET_TOOLKIT" = "mac" -o "$MOZ_WIDGET_TOOLKIT" = "cocoa"; then
         QUARTZ_SURFACE_FEATURE="#define CAIRO_HAS_QUARTZ_SURFACE 1"
         QUARTZ_IMAGE_SURFACE_FEATURE="#define CAIRO_HAS_QUARTZ_IMAGE_SURFACE 1"
         QUARTZ_FONT_FEATURE="#define CAIRO_HAS_QUARTZ_FONT 1"
     fi
     if test "$MOZ_WIDGET_TOOLKIT" = "windows"; then
         WIN32_SURFACE_FEATURE="#define CAIRO_HAS_WIN32_SURFACE 1"
         WIN32_FONT_FEATURE="#define CAIRO_HAS_WIN32_FONT 1"
@@ -7507,16 +7568,17 @@ if test "$MOZ_TREE_CAIRO"; then
     AC_SUBST(OS2_SURFACE_FEATURE)
     AC_SUBST(BEOS_SURFACE_FEATURE)
     AC_SUBST(GLITZ_SURFACE_FEATURE)
     AC_SUBST(DIRECTFB_SURFACE_FEATURE)
     AC_SUBST(FT_FONT_FEATURE)
     AC_SUBST(WIN32_FONT_FEATURE)
     AC_SUBST(QUARTZ_FONT_FEATURE)
     AC_SUBST(PNG_FUNCTIONS_FEATURE)
+    AC_SUBST(QPAINTER_SURFACE_FEATURE)
 
     if test "$_WIN32_MSVC"; then
         MOZ_CAIRO_LIBS='$(DEPTH)/gfx/cairo/cairo/src/mozcairo.lib $(DEPTH)/gfx/cairo/libpixman/src/mozlibpixman.lib'
         if test "$MOZ_ENABLE_GLITZ"; then
             MOZ_CAIRO_LIBS="$MOZ_CAIRO_LIBS "'$(DEPTH)/gfx/cairo/glitz/src/mozglitz.lib $(DEPTH)/gfx/cairo/glitz/src/wgl/mozglitzwgl.lib'
         fi
     else
         MOZ_CAIRO_LIBS='$(DEPTH)/gfx/cairo/cairo/src/$(LIB_PREFIX)mozcairo.$(LIB_SUFFIX) $(DEPTH)/gfx/cairo/libpixman/src/$(LIB_PREFIX)mozlibpixman.$(LIB_SUFFIX)'" $CAIRO_FT_LIBS"
--- a/embedding/components/build/Makefile.in
+++ b/embedding/components/build/Makefile.in
@@ -117,17 +117,17 @@ ifdef MOZ_PROFILESHARING
 SHARED_LIBRARY_LIBS += $(DIST)/lib/$(LIB_PREFIX)profilesharingsetup_s.$(LIB_SUFFIX)
 LOCAL_INCLUDES += -I$(srcdir)/../profilesharingsetup/src
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
 LOCAL_INCLUDES += -I$(srcdir)/../printingui/src/os2 
 endif
 
-ifneq (,$(filter gtk2 beos photon, $(MOZ_WIDGET_TOOLKIT)))
+ifneq (,$(filter qt gtk2 beos photon, $(MOZ_WIDGET_TOOLKIT)))
 LOCAL_INCLUDES += -I$(srcdir)/../printingui/src/unixshared 
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 LOCAL_INCLUDES += -I$(srcdir)/../printingui/src/win 
 ifneq ($(OS_ARCH), WINCE)
 OS_LIBS	+= $(call EXPAND_LIBNAME,winspool comdlg32)
 endif
--- a/embedding/components/printingui/src/Makefile.in
+++ b/embedding/components/printingui/src/Makefile.in
@@ -37,17 +37,17 @@
 
 DEPTH		= ../../../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-ifneq (,$(filter gtk2 photon beos,$(MOZ_WIDGET_TOOLKIT)))
+ifneq (,$(filter qt gtk2 photon beos,$(MOZ_WIDGET_TOOLKIT)))
 PLATFORM_DIR += unixshared
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
 PLATFORM_DIR = os2
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
new file mode 100644
--- /dev/null
+++ b/extensions/widgetutils/Makefile.in
@@ -0,0 +1,33 @@
+
+DEPTH=../..
+topsrcdir=@top_srcdir@
+srcdir=@srcdir@
+VPATH=@srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE	= widgetutils
+XPI_NAME = widgetutils
+
+ifdef MOZ_XUL_APP
+INSTALL_EXTENSION_ID = widgetutils@extensions.mozilla.org
+DIST_FILES = install.rdf
+NO_JAR_AUTO_REG        = 1
+USE_EXTENSION_MANIFEST = 1
+XPI_PKGNAME            = widgetutils-$(MOZ_APP_VERSION)
+
+XULAPP_DEFINES = \
+	-DFIREFOX_VERSION=$(FIREFOX_VERSION) \
+	-DTHUNDERBIRD_VERSION=$(THUNDERBIRD_VERSION) \
+	-DEXTENSION_VERSION=$(MOZILLA_VERSION) \
+	$(NULL)
+
+ifdef TARGET_XPCOM_ABI
+XULAPP_DEFINES += -DEM_ABI=$(OS_TARGET)_$(TARGET_XPCOM_ABI)
+endif
+endif
+
+DIRS    = src
+#DIRS   += public
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/extensions/widgetutils/install.rdf
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+
+#filter substitution
+
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+  <Description about="urn:mozilla:install-manifest">
+    <em:id>widgetutils@extensions.mozilla.org</em:id>
+    <em:version>@EXTENSION_VERSION@</em:version>
+
+#ifdef EM_ABI
+    <em:targetPlatform>@EM_ABI@</em:targetPlatform>
+#endif
+
+    <em:targetApplication>
+      <!-- Firefox -->
+      <Description>
+        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+        <em:minVersion>@FIREFOX_VERSION@</em:minVersion>
+        <em:maxVersion>@FIREFOX_VERSION@</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+
+    <em:targetApplication>
+      <!-- Thunderbird -->
+      <Description>
+        <em:id>{3550f703-e582-4d05-9a08-453d09bdfdc6}</em:id>
+        <em:minVersion>@THUNDERBIRD_VERSION@</em:minVersion>
+        <em:maxVersion>@THUNDERBIRD_VERSION@</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+
+    <!-- front-end metadata -->
+    <em:name>WidgetUtils service</em:name>
+    <em:description>Provide scrolling by mouse feature.</em:description>
+    <em:creator>mozilla.org</em:creator>
+    <em:contributor>Oleg Romashin &lt;romaxa@gmail.com&gt;</em:contributor>
+    <em:homepageURL>http://hg.mozilla.org</em:homepageURL>
+  </Description>
+</RDF>
new file mode 100644
--- /dev/null
+++ b/extensions/widgetutils/src/Makefile.in
@@ -0,0 +1,91 @@
+# vim:set ts=8 sw=8 sts=8 noet:
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Mozilla Browser code.
+#
+# The Initial Developer of the Original Code is Google Inc.
+# Portions created by the Initial Developer are Copyright (C) 2005
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#  Oleg Romashin <romaxa@gmail.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE		= widgetutils
+XPI_NAME	= widgetutils
+LIBRARY_NAME    = widgetutils
+ifneq ($(OS_ARCH),WINNT)
+SHORT_LIBNAME = widgetutils
+endif
+FORCE_SHARED_LIB = 1
+IS_COMPONENT = 1
+
+REQUIRES = \
+	dom \
+	layout \
+	content \
+	widget \
+	necko \
+	windowwatcher \
+	xpcom \
+	string \
+	pref \
+	gfx \
+	locale \
+	docshell \
+	uriloader \
+	webbrwsr \
+	imglib2 \
+	view \
+	$(NULL)
+
+CPPSRCS		= nsWidgetUtils.cpp
+
+EXTRA_DSO_LDOPTS = \
+	$(XPCOM_GLUE_LDOPTS) \
+	$(NSPR_LIBS) \
+	$(NULL)
+
+EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)
+
+EXPORT_RESOURCE = \
+	$(NULL)
+
+ifdef TARGET_XPCOM_ABI
+FINAL_TARGET=$(DIST)/xpi-stage/$(XPI_NAME)/platform/$(OS_TARGET)_$(TARGET_XPCOM_ABI)
+endif
+
+#EXTRA_COMPONENTS = $(srcdir)/SimpleTest.js
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/extensions/widgetutils/src/nsWidgetUtils.cpp
@@ -0,0 +1,649 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 tw=80 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla's Element Optimizeing extension.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Oleg Romashin <romaxa@gmail.com> (original author)
+ *   Brad Lassey <blassey@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsCURILoader.h"
+#include "nsICategoryManager.h"
+#include "nsIDOMAbstractView.h"
+#include "nsIDOMDocument.h"
+#include "nsIDOMDocumentView.h"
+#include "nsIDOMHTMLElement.h"
+#include "nsIDOMHTMLIFrameElement.h"
+#include "nsIDOMNSDocument.h"
+#include "nsIDOMNSElement.h"
+#include "nsIDOMNSHTMLElement.h"
+#include "nsIDOMNode.h"
+#include "nsIDOMNodeList.h"
+#include "nsIDOMWindow.h"
+#include "nsIDOMWindowCollection.h"
+#include "nsIDocument.h"
+#include "nsIGenericFactory.h"
+#include "nsIObserver.h"
+#include "nsIPref.h"
+#include "nsIPresShell.h"
+#include "nsIStyleSheetService.h"
+#include "nsIWebProgress.h"
+#include "nsIWebProgressListener.h"
+#include "nsIWindowWatcher.h"
+#include "nsNetUtil.h"
+#include "nsRect.h"
+#include "nsStringGlue.h"
+#include "nsWeakReference.h"
+#include "nsIWebBrowser.h"
+#include "nsIObserverService.h"
+#include "nsIDOMEventTarget.h"
+#include "nsPIDOMWindow.h"
+#include "nsIDOMWindow.h"
+//#include ".h"
+#include "nsIDOM3EventTarget.h"
+#include "nsIDOMKeyListener.h"
+#include "nsIDOMCompositionListener.h"
+#include "nsIDOMTextListener.h"
+#include "nsIDOMMouseMotionListener.h"
+#include "nsIDOMMouseListener.h"
+#include "nsIDOMMouseEvent.h"
+#include "nsIDOMNSEvent.h"
+#include "nsIView.h"
+#include "nsGUIEvent.h"
+#include "nsIViewManager.h"
+#include "nsIContentPolicy.h"
+#include "nsIDocShellTreeItem.h"
+#include "nsIContent.h"
+#include "nsITimer.h"
+
+const int MIN_INT =((int) (1 << (sizeof(int) * 8 - 1)));
+
+static int g_lastX=MIN_INT;
+static int g_lastY=MIN_INT;
+static PRInt32 g_panning = 0;
+static PRBool g_is_scrollable = PR_FALSE;
+
+#define EM_MULT 16.
+#define NS_FRAME_HAS_RELATIVE_SIZE 0x01000000
+#define NS_FRAME_HAS_OPTIMIZEDVIEW 0x02000000
+#define BEHAVIOR_ACCEPT nsIPermissionManager::ALLOW_ACTION
+#define BEHAVIOR_REJECT nsIPermissionManager::DENY_ACTION
+#define BEHAVIOR_NOFOREIGN 3
+#define NUMBER_OF_TYPES 13
+
+// TODO auto reload nsWidgetUtils in C.
+class nsWidgetUtils : public nsIObserver,
+                      public nsIDOMMouseMotionListener,
+                      public nsIDOMMouseListener,
+                      public nsIContentPolicy,
+                      public nsSupportsWeakReference
+{
+public:
+  nsWidgetUtils();
+  virtual ~nsWidgetUtils();
+
+  // nsIDOMMouseMotionListener
+  NS_IMETHOD MouseMove(nsIDOMEvent* aDOMEvent);
+  NS_IMETHOD DragMove(nsIDOMEvent* aMouseEvent);
+  NS_IMETHOD HandleEvent(nsIDOMEvent* aDOMEvent);
+
+  // nsIDOMMouseListener
+  NS_IMETHOD MouseDown(nsIDOMEvent* aDOMEvent);
+  NS_IMETHOD MouseUp(nsIDOMEvent* aDOMEvent);
+  NS_IMETHOD MouseClick(nsIDOMEvent* aDOMEvent);
+  NS_IMETHOD MouseDblClick(nsIDOMEvent* aDOMEvent);
+  NS_IMETHOD MouseOver(nsIDOMEvent* aDOMEvent);
+  NS_IMETHOD MouseOut(nsIDOMEvent* aDOMEvent);
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIOBSERVER 
+  NS_DECL_NSICONTENTPOLICY
+
+private:
+  nsresult Init(void);
+  void RemoveWindowListeners(nsIDOMWindow *aDOMWin);
+  void GetChromeEventHandler(nsIDOMWindow *aDOMWin, nsIDOMEventTarget **aChromeTarget);
+  void AttachWindowListeners(nsIDOMWindow *aDOMWin);
+  PRBool IsXULNode(nsIDOMNode *aNode, PRUint32 *aType = 0);
+  nsresult GetDOMWindowByNode(nsIDOMNode *aNode, nsIDOMWindow * *aDOMWindow);
+  nsresult UpdateFromEvent(nsIDOMEvent *aDOMEvent, nsIWidget * *aWidget = nsnull, nsIViewManager * *aViewManager = nsnull);
+
+  static void StopPanningCallback(nsITimer *timer, void *closure);
+
+  nsCOMPtr<nsIWidget> mWidget;
+  nsCOMPtr<nsIViewManager> mViewManager;
+  nsCOMPtr<nsITimer> mTimer;
+};
+
+nsWidgetUtils::nsWidgetUtils()
+{
+  Init();
+}
+
+NS_IMETHODIMP
+nsWidgetUtils::Init()
+{
+  nsresult rv;
+  nsCOMPtr<nsIObserverService> obsSvc =
+    do_GetService("@mozilla.org/observer-service;1");
+  NS_ENSURE_STATE(obsSvc);
+
+  rv = obsSvc->AddObserver(this, "domwindowopened", PR_FALSE);
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = obsSvc->AddObserver(this, "domwindowclosed", PR_FALSE);
+  NS_ENSURE_SUCCESS(rv, rv);
+  mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+}
+
+nsresult
+nsWidgetUtils::UpdateFromEvent(nsIDOMEvent *aDOMEvent, nsIWidget * *aWidget, nsIViewManager * *aViewManager)
+{
+  nsCOMPtr <nsIDOMMouseEvent> mouseEvent;
+  mouseEvent = do_QueryInterface(aDOMEvent);
+  if (!mouseEvent)
+    return NS_OK;
+
+  ((nsIDOMMouseEvent*)mouseEvent)->GetScreenX(&g_lastX);
+  ((nsIDOMMouseEvent*)mouseEvent)->GetScreenY(&g_lastY);
+
+  nsCOMPtr<nsIDOMWindow> mWindow;
+  nsCOMPtr<nsIDOMNode> mNode;
+  nsCOMPtr<nsIDOMNode> mOrigNode;
+
+  PRUint32 type = 0;
+  PRBool isXul = PR_FALSE;
+  {
+    nsCOMPtr <nsIDOMNSEvent> aEvent = do_QueryInterface(aDOMEvent);
+    nsCOMPtr<nsIDOMEventTarget> eventOrigTarget;
+    if (aEvent)
+      aEvent->GetOriginalTarget(getter_AddRefs(eventOrigTarget));
+    if (eventOrigTarget)
+      mOrigNode = do_QueryInterface(eventOrigTarget);
+    isXul = IsXULNode(mOrigNode, &type);
+
+  }
+  if (isXul)
+    return NS_ERROR_FAILURE;
+
+  nsCOMPtr<nsIDOMEventTarget> eventTarget;
+  aDOMEvent->GetTarget(getter_AddRefs(eventTarget));
+  if (eventTarget)
+    mNode = do_QueryInterface(eventTarget);
+
+  if (!mNode)
+    return NS_OK;
+
+  GetDOMWindowByNode(mNode, getter_AddRefs(mWindow));
+  if (!mWindow)
+    return NS_OK;
+  nsCOMPtr<nsIDocument> doc;
+  nsCOMPtr<nsIDOMDocument> domDoc;
+  mWindow->GetDocument(getter_AddRefs(domDoc));
+  doc = do_QueryInterface(domDoc);
+  if (!doc) return NS_OK;
+  // the only case where there could be more shells in printpreview
+  nsIPresShell *shell = doc->GetPrimaryShell();
+  NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE);
+  mViewManager = shell->GetViewManager();
+  NS_ENSURE_TRUE(mViewManager, NS_ERROR_FAILURE);
+  mViewManager->GetWidget(getter_AddRefs(mWidget));
+  NS_ENSURE_TRUE(mWidget, NS_ERROR_FAILURE);
+  if (aWidget)
+    NS_ADDREF(*aWidget = mWidget);
+  if (aViewManager)
+    NS_ADDREF(*aViewManager = mViewManager);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWidgetUtils::MouseDown(nsIDOMEvent* aDOMEvent)
+{
+  g_is_scrollable = PR_FALSE;
+  // Return TRUE from your signal handler to mark the event as consumed.
+  if (NS_FAILED(UpdateFromEvent(aDOMEvent)))
+    return NS_OK;
+  g_is_scrollable = PR_TRUE;
+  if (g_is_scrollable) {
+     aDOMEvent->StopPropagation();
+     aDOMEvent->PreventDefault();
+  }
+  return NS_OK;
+}
+
+/* static */ void
+nsWidgetUtils::StopPanningCallback(nsITimer *timer, void *closure)
+{
+  g_panning = PR_FALSE;
+}
+
+NS_IMETHODIMP
+nsWidgetUtils::MouseUp(nsIDOMEvent* aDOMEvent)
+{
+  nsCOMPtr <nsIDOMMouseEvent> mouseEvent;
+  mouseEvent = do_QueryInterface(aDOMEvent);
+  if (!mouseEvent)
+    return NS_OK;
+  // Return TRUE from your signal handler to mark the event as consumed.
+  g_lastX = MIN_INT;
+  g_lastY = MIN_INT;
+  g_is_scrollable = PR_FALSE;
+  if (g_panning) {
+     aDOMEvent->StopPropagation();
+     aDOMEvent->PreventDefault();
+     nsresult rv;
+     if (mTimer) {
+       rv = mTimer->InitWithFuncCallback(nsWidgetUtils::StopPanningCallback,
+                                        nsnull, 500, nsITimer::TYPE_ONE_SHOT);
+       if (NS_SUCCEEDED(rv))
+         return NS_OK;
+     }
+     g_panning = PR_FALSE;
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWidgetUtils::MouseMove(nsIDOMEvent* aDOMEvent)
+{
+  if (!g_is_scrollable) return NS_OK;
+
+  nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aDOMEvent);
+  if (!mouseEvent)
+    return NS_OK;
+  int x, y;
+  ((nsIDOMMouseEvent*)mouseEvent)->GetScreenX(&x);
+  ((nsIDOMMouseEvent*)mouseEvent)->GetScreenY(&y);
+
+  int dx = g_lastX - x;
+  int dy = g_lastY - y;
+  if(g_lastX == MIN_INT || g_lastY == MIN_INT)
+    return NS_OK;
+
+  nsIView *aView = nsnull;
+  mViewManager->GetRootView(aView);
+  if (!aView)
+    if (NS_FAILED(UpdateFromEvent(aDOMEvent)))
+      return NS_OK;
+
+  nsEventStatus statusX;
+  nsMouseScrollEvent scrollEventX(PR_TRUE, NS_MOUSE_SCROLL, mWidget);
+  scrollEventX.delta = dx;
+  scrollEventX.scrollFlags = nsMouseScrollEvent::kIsHorizontal | nsMouseScrollEvent::kIsPixels;
+  mViewManager->DispatchEvent(&scrollEventX, &statusX);
+  if(statusX != nsEventStatus_eIgnore ){
+    if (dx > 5)
+      g_panning = PR_TRUE;
+    g_lastX = x;
+  }
+
+  nsEventStatus statusY;
+  nsMouseScrollEvent scrollEventY(PR_TRUE, NS_MOUSE_SCROLL, mWidget);
+  scrollEventY.delta = dy;
+  scrollEventY.scrollFlags = nsMouseScrollEvent::kIsVertical | nsMouseScrollEvent::kIsPixels;
+  mViewManager->DispatchEvent(&scrollEventY, &statusY);
+  if(statusY != nsEventStatus_eIgnore ){
+    if (dy > 5)
+      g_panning = PR_TRUE;
+    g_lastY = y;
+  }
+  if (g_panning) {
+     aDOMEvent->StopPropagation();
+     aDOMEvent->PreventDefault();
+  }
+
+  return NS_OK;
+}
+
+// nsIContentPolicy Implementation
+NS_IMETHODIMP
+nsWidgetUtils::ShouldLoad(PRUint32          aContentType,
+                          nsIURI           *aContentLocation,
+                          nsIURI           *aRequestingLocation,
+                          nsISupports      *aRequestingContext,
+                          const nsACString &aMimeGuess,
+                          nsISupports      *aExtra,
+                          PRInt16          *aDecision)
+{
+    *aDecision = nsIContentPolicy::ACCEPT;
+    nsresult rv;
+
+    if (aContentType != nsIContentPolicy::TYPE_DOCUMENT)
+        return NS_OK;
+
+    // we can't do anything without this
+    if (!aContentLocation)
+        return NS_OK;
+
+    nsCAutoString scheme;
+    rv = aContentLocation->GetScheme(scheme);
+    nsCAutoString lscheme;
+    ToLowerCase(scheme, lscheme);
+    if (!lscheme.EqualsLiteral("ftp") &&
+        !lscheme.EqualsLiteral("http") &&
+        !lscheme.EqualsLiteral("https"))
+        return NS_OK;
+    if (g_panning > 0)
+      *aDecision = nsIContentPolicy::REJECT_REQUEST;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWidgetUtils::MouseClick(nsIDOMEvent* aDOMEvent)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWidgetUtils::MouseDblClick(nsIDOMEvent* aDOMEvent)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWidgetUtils::HandleEvent(nsIDOMEvent* aDOMEvent)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWidgetUtils::MouseOver(nsIDOMEvent* aDOMEvent)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWidgetUtils::MouseOut(nsIDOMEvent* aDOMEvent)
+{
+  return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsWidgetUtils::DragMove(nsIDOMEvent* aDOMEvent)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWidgetUtils::ShouldProcess(PRUint32          aContentType,
+                             nsIURI           *aContentLocation,
+                             nsIURI           *aRequestingLocation,
+                             nsISupports      *aRequestingContext,
+                             const nsACString &aMimeGuess,
+                             nsISupports      *aExtra,
+                             PRInt16          *aDecision)
+{
+    *aDecision = nsIContentPolicy::ACCEPT;
+    return NS_OK;
+}
+
+PRBool
+nsWidgetUtils::IsXULNode(nsIDOMNode *aNode, PRUint32 *aType)
+{
+  PRBool retval = PR_FALSE;
+  if (!aNode) return retval;
+
+  nsString sorigNode;
+  aNode->GetNodeName(sorigNode);
+  if (sorigNode.EqualsLiteral("#document"))
+    return retval;
+  retval = StringBeginsWith(sorigNode, NS_LITERAL_STRING("xul:"));
+
+  if (!aType) return retval;
+
+  if (sorigNode.EqualsLiteral("xul:thumb")
+      || sorigNode.EqualsLiteral("xul:vbox")
+      || sorigNode.EqualsLiteral("xul:spacer"))
+    *aType = PR_FALSE; // Magic
+  else if (sorigNode.EqualsLiteral("xul:slider"))
+    *aType = 2; // Magic
+  else if (sorigNode.EqualsLiteral("xul:scrollbarbutton"))
+    *aType = 3; // Magic
+
+  return retval;
+}
+
+nsresult
+nsWidgetUtils::GetDOMWindowByNode(nsIDOMNode *aNode, nsIDOMWindow * *aDOMWindow)
+{
+  nsresult rv;
+  nsCOMPtr<nsIDOMDocument> nodeDoc;
+  rv = aNode->GetOwnerDocument(getter_AddRefs(nodeDoc));
+  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIDOMDocumentView> docView = do_QueryInterface(nodeDoc, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIDOMAbstractView> absView;
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = docView->GetDefaultView(getter_AddRefs(absView));
+  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(absView, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+  *aDOMWindow = window;
+  NS_IF_ADDREF(*aDOMWindow);
+  return rv;
+}
+
+void
+nsWidgetUtils::GetChromeEventHandler(nsIDOMWindow *aDOMWin,
+                                 nsIDOMEventTarget **aChromeTarget)
+{
+    nsCOMPtr<nsPIDOMWindow> privateDOMWindow(do_QueryInterface(aDOMWin));
+    nsPIDOMEventTarget* chromeEventHandler = nsnull;
+    if (privateDOMWindow) {
+        chromeEventHandler = privateDOMWindow->GetChromeEventHandler();
+    }
+
+    nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(chromeEventHandler));
+
+    *aChromeTarget = target;
+    NS_IF_ADDREF(*aChromeTarget);
+}
+
+void
+nsWidgetUtils::RemoveWindowListeners(nsIDOMWindow *aDOMWin)
+{
+    nsresult rv;
+    nsCOMPtr<nsIDOMEventTarget> chromeEventHandler;
+    GetChromeEventHandler(aDOMWin, getter_AddRefs(chromeEventHandler));
+    if (!chromeEventHandler) {
+        return;
+    }
+
+    // Use capturing, otherwise the normal find next will get activated when ours should
+    nsCOMPtr<nsPIDOMEventTarget> piTarget(do_QueryInterface(chromeEventHandler));
+
+    // Remove DOM Text listener for IME text events
+    rv = piTarget->RemoveEventListenerByIID(static_cast<nsIDOMMouseListener*>(this),
+                                            NS_GET_IID(nsIDOMMouseListener));
+    if (NS_FAILED(rv)) {
+        NS_WARNING("Failed to add Mouse Motion listener\n");
+        return;
+    }
+    rv = piTarget->RemoveEventListenerByIID(static_cast<nsIDOMMouseMotionListener*>(this),
+                                            NS_GET_IID(nsIDOMMouseMotionListener));
+    if (NS_FAILED(rv)) {
+        NS_WARNING("Failed to add Mouse Motion listener\n");
+        return;
+    }
+}
+
+void
+nsWidgetUtils::AttachWindowListeners(nsIDOMWindow *aDOMWin)
+{
+    nsresult rv;
+    nsCOMPtr<nsIDOMEventTarget> chromeEventHandler;
+    GetChromeEventHandler(aDOMWin, getter_AddRefs(chromeEventHandler));
+    if (!chromeEventHandler) {
+        return;
+    }
+
+    // Use capturing, otherwise the normal find next will get activated when ours should
+    nsCOMPtr<nsPIDOMEventTarget> piTarget(do_QueryInterface(chromeEventHandler));
+
+    // Attach menu listeners, this will help us ignore keystrokes meant for menus
+    rv = piTarget->AddEventListenerByIID(static_cast<nsIDOMMouseListener*>(this),
+                                         NS_GET_IID(nsIDOMMouseListener));
+    if (NS_FAILED(rv)) {
+        NS_WARNING("Failed to add Mouse Motion listener\n");
+        return;
+    }
+    rv = piTarget->AddEventListenerByIID(static_cast<nsIDOMMouseMotionListener*>(this),
+                                         NS_GET_IID(nsIDOMMouseMotionListener));
+    if (NS_FAILED(rv)) {
+        NS_WARNING("Failed to add Mouse Motion listener\n");
+        return;
+    }
+}
+
+nsWidgetUtils::~nsWidgetUtils()
+{
+}
+
+NS_IMPL_ISUPPORTS5(nsWidgetUtils, nsIObserver, nsIDOMMouseMotionListener, nsIDOMMouseListener, nsIContentPolicy, nsISupportsWeakReference)
+
+NS_IMETHODIMP
+nsWidgetUtils::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData)
+{
+  nsresult rv;
+  if (!strcmp(aTopic,"domwindowopened")) 
+  {
+    nsCOMPtr<nsIDOMWindow> chromeWindow = do_QueryInterface(aSubject);
+    if (chromeWindow)
+      AttachWindowListeners(chromeWindow);
+    return NS_OK;
+  }
+
+  if (!strcmp(aTopic,"domwindowclosed")) 
+  {
+    nsCOMPtr<nsIDOMWindow> chromeWindow = do_QueryInterface(aSubject);
+    RemoveWindowListeners(chromeWindow);
+    return NS_OK;
+  }
+
+  return NS_OK;
+}
+
+//------------------------------------------------------------------------------
+//  XPCOM REGISTRATION BELOW
+//------------------------------------------------------------------------------
+
+#define WidgetUtils_CID \
+{  0x0ced17b6, 0x96ed, 0x4030, \
+{0xa1, 0x34, 0x77, 0xcb, 0x66, 0x10, 0xa8, 0xf6} }
+
+#define WidgetUtils_ContractID "@mozilla.org/extensions/widgetutils;1"
+
+static NS_METHOD WidgetUtilsRegistration(nsIComponentManager *aCompMgr,
+                                         nsIFile *aPath,
+                                         const char *registryLocation,
+                                         const char *componentType,
+                                         const nsModuleComponentInfo *info)
+{
+    nsresult rv;
+
+    nsCOMPtr<nsIServiceManager> servman = do_QueryInterface((nsISupports*)aCompMgr, &rv);
+    if (NS_FAILED(rv))
+        return rv;
+
+    nsCOMPtr<nsICategoryManager> catman;
+    servman->GetServiceByContractID(NS_CATEGORYMANAGER_CONTRACTID,
+                                    NS_GET_IID(nsICategoryManager),
+                                    getter_AddRefs(catman));
+
+    if (NS_FAILED(rv))
+        return rv;
+
+    char* previous = nsnull;
+    rv = catman->AddCategoryEntry("app-startup",
+                                  "WidgetUtils",
+                                  WidgetUtils_ContractID,
+                                  PR_TRUE,
+                                  PR_TRUE,
+                                  &previous);
+    if (previous)
+        nsMemory::Free(previous);
+    rv = catman->AddCategoryEntry("content-policy",
+                                  "WidgetUtils",
+                                  WidgetUtils_ContractID,
+                                  PR_TRUE,
+                                  PR_TRUE,
+                                  &previous);
+    if (previous)
+        nsMemory::Free(previous);
+
+    return rv;
+}
+
+static NS_METHOD WidgetUtilsUnregistration(nsIComponentManager *aCompMgr,
+                                           nsIFile *aPath,
+                                           const char *registryLocation,
+                                           const nsModuleComponentInfo *info)
+{
+    nsresult rv;
+
+    nsCOMPtr<nsIServiceManager> servman = do_QueryInterface((nsISupports*)aCompMgr, &rv);
+    if (NS_FAILED(rv))
+        return rv;
+
+    nsCOMPtr<nsICategoryManager> catman;
+    servman->GetServiceByContractID(NS_CATEGORYMANAGER_CONTRACTID,
+                                    NS_GET_IID(nsICategoryManager),
+                                    getter_AddRefs(catman));
+
+    if (NS_FAILED(rv))
+        return rv;
+
+    rv = catman->DeleteCategoryEntry("app-startup",
+                                     "WidgetUtils",
+                                     PR_TRUE);
+    rv = catman->DeleteCategoryEntry("content-policy",
+                                     "WidgetUtils",
+                                     PR_TRUE);
+
+    return rv;
+}
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsWidgetUtils)
+
+  static const nsModuleComponentInfo components[] =
+{
+  { "nsWidgetUtilsService",
+    WidgetUtils_CID,
+    WidgetUtils_ContractID,
+    nsWidgetUtilsConstructor,
+    WidgetUtilsRegistration,
+    WidgetUtilsUnregistration
+  }
+};
+
+NS_IMPL_NSGETMODULE(nsWidgetUtilsModule, components)
--- a/gfx/cairo/cairo/src/Makefile.in
+++ b/gfx/cairo/cairo/src/Makefile.in
@@ -175,16 +175,22 @@ CPPSRCS += cairo-beos-surface.cpp
 EXPORTS += cairo-beos.h
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 CSRCS   += $(PSPDF_BASE_CSRCS) $(PDF_CSRCS) $(PS_CSRCS)
 EXPORTS += $(PDF_EXPORTS) $(PS_EXPORTS)
 endif
 
+ifeq ($(MOZ_WIDGET_TOOLKIT),qt)
+CPPSRCS += cairo-qpainter-surface.cpp
+EXPORTS += cairo-qpainter.h
+OS_INCLUDES += $(MOZ_QT_CFLAGS)
+endif
+
 ifdef BUILD_CAIRO_SVG
 CSRCS	+= cairo-svg-surface.c
 EXPORTS += cairo-svg.h
 endif
 
 ifdef MOZ_X11
 CSRCS   += cairo-xlib-surface.c \
 	   cairo-xlib-screen.c \
--- a/gfx/cairo/cairo/src/cairo-features.h.in
+++ b/gfx/cairo/cairo/src/cairo-features.h.in
@@ -78,16 +78,18 @@
 @OS2_SURFACE_FEATURE@
 
 @BEOS_SURFACE_FEATURE@
 
 @GLITZ_SURFACE_FEATURE@
 
 @DIRECTFB_SURFACE_FEATURE@
 
+@QPAINTER_SURFACE_FEATURE@
+
 @FT_FONT_FEATURE@
 
 @WIN32_FONT_FEATURE@
 
 @QUARTZ_FONT_FEATURE@
 
 @PNG_FUNCTIONS_FEATURE@
 
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-qpainter-surface.cpp
@@ -0,0 +1,1800 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2008 Mozilla Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation.
+ *
+ * Contributor(s):
+ *      Vladimir Vukicevic <vladimir@mozilla.com>
+ */
+
+/* Get INT16_MIN etc. as per C99 */
+#define __STDC_LIMIT_MACROS
+
+#include "cairoint.h"
+
+#include "cairo-qpainter.h"
+#include <memory>
+
+#include <QtGui/QPainter>
+#include <QtGui/QPaintEngine>
+#include <QtGui/QPaintDevice>
+#include <QtGui/QImage>
+#include <QtGui/QPixmap>
+#include <QtGui/QBrush>
+#include <QtGui/QPen>
+#include <QtGui/QWidget>
+#include <QtGui/QX11Info>
+
+#ifdef CAIRO_HAS_XLIB_XRENDER_SURFACE
+#include "cairo-xlib.h"
+#include "cairo-xlib-xrender.h"
+// I hate X
+#undef Status
+#undef CursorShape
+#undef Bool
+#endif
+
+#include <sys/time.h>
+
+#if 0
+#define D(x)  x
+#else
+#define D(x) do { } while(0)
+#endif
+
+#if 0
+#define DP(x) if (g_dump_path) { x; }
+#else
+#define DP(x) do { } while(0)
+#endif
+
+#ifndef CAIRO_INT_STATUS_SUCCESS
+#define CAIRO_INT_STATUS_SUCCESS ((cairo_int_status_t) CAIRO_STATUS_SUCCESS)
+#endif
+
+typedef struct {
+    cairo_surface_t base;
+
+    QPainter *p;
+
+    /* The pixmap/image constructors will store their objects here */
+    QPixmap *pixmap;
+    QImage *image;
+
+    QRect window;
+
+    bool has_clipping;
+    QRect clip_bounds;
+
+    // if this is true, calls to intersect_clip_path won't
+    // update the clip_bounds rect
+    bool no_update_clip_bounds;
+
+    cairo_image_surface_t *image_equiv;
+
+#if defined(Q_WS_X11) && defined(CAIRO_HAS_XLIB_XRENDER_SURFACE)
+    /* temporary, so that we can share the xlib surface's glyphs code */
+    cairo_surface_t *xlib_equiv;
+    bool xlib_has_clipping;
+    QRect xlib_clip_bounds;
+    int xlib_clip_serial;
+    QPoint redir_offset;
+#endif
+
+    cairo_bool_t supports_porter_duff;
+} cairo_qpainter_surface_t;
+
+/* Will be set to TRUE if we ever try to create a QPixmap and end
+ * up with one without an alpha channel.
+ */
+static cairo_bool_t _qpixmaps_have_no_alpha = FALSE;
+
+static cairo_int_status_t
+_cairo_qpainter_surface_paint (void *abstract_surface,
+                               cairo_operator_t op,
+                               cairo_pattern_t *source);
+
+/* some debug timing stuff */
+static int g_dump_path = 1;
+static struct timeval timer_start_val;
+#if 0
+static void tstart() {
+    gettimeofday(&timer_start_val, NULL);
+}
+
+static void tend(const char *what = NULL) {
+    struct timeval timer_stop;
+    gettimeofday(&timer_stop, NULL);
+
+    double ms_start = timer_start_val.tv_sec * 1000.0 + timer_start_val.tv_usec / 1000.0;
+    double ms_end = timer_stop.tv_sec * 1000.0 + timer_stop.tv_usec / 1000.0;
+
+    if (ms_end - ms_start > 1.0)
+	fprintf (stderr, "******* %s elapsed: %f ms\n", what ? what : "(timer)", ms_end - ms_start);
+}
+#else
+static void tstart() { }
+static void tend(const char *what = NULL) { }
+#endif
+
+/**
+ ** Helper methods
+ **/
+static const char *
+_opstr (cairo_operator_t op)
+{
+    const char *ops[] = {
+        "CLEAR",
+        "SOURCE",
+        "OVER",
+        "IN",
+        "OUT",
+        "ATOP",
+        "DEST",
+        "DEST_OVER",
+        "DEST_IN",
+        "DEST_OUT",
+        "DEST_ATOP",
+        "XOR",
+        "ADD",
+        "SATURATE"
+    };
+
+    if (op < CAIRO_OPERATOR_CLEAR || op > CAIRO_OPERATOR_SATURATE)
+        return "(\?\?\?)";
+
+    return ops[op];
+}
+
+static QPainter::CompositionMode
+_qpainter_compositionmode_from_cairo_op (cairo_operator_t op)
+{
+    switch (op) {
+    case CAIRO_OPERATOR_CLEAR:
+        return QPainter::CompositionMode_Clear;
+
+    case CAIRO_OPERATOR_SOURCE:
+        return QPainter::CompositionMode_Source;
+    case CAIRO_OPERATOR_OVER:
+        return QPainter::CompositionMode_SourceOver;
+    case CAIRO_OPERATOR_IN:
+        return QPainter::CompositionMode_SourceIn;
+    case CAIRO_OPERATOR_OUT:
+        return QPainter::CompositionMode_SourceOut;
+    case CAIRO_OPERATOR_ATOP:
+        return QPainter::CompositionMode_SourceAtop;
+
+    case CAIRO_OPERATOR_DEST:
+        return QPainter::CompositionMode_Destination;
+    case CAIRO_OPERATOR_DEST_OVER:
+        return QPainter::CompositionMode_DestinationOver;
+    case CAIRO_OPERATOR_DEST_IN:
+        return QPainter::CompositionMode_DestinationIn;
+    case CAIRO_OPERATOR_DEST_OUT:
+        return QPainter::CompositionMode_DestinationOut;
+    case CAIRO_OPERATOR_DEST_ATOP:
+        return QPainter::CompositionMode_DestinationAtop;
+
+    case CAIRO_OPERATOR_XOR:
+        return QPainter::CompositionMode_Xor;
+    case CAIRO_OPERATOR_ADD:
+        return QPainter::CompositionMode_SourceOver; // XXX?
+    case CAIRO_OPERATOR_SATURATE:
+        return QPainter::CompositionMode_SourceOver; // XXX?
+    }
+
+    return QPainter::CompositionMode_Source;
+}
+
+static cairo_format_t
+_cairo_format_from_qimage_format (QImage::Format fmt)
+{
+    switch (fmt) {
+    case QImage::Format_ARGB32_Premultiplied:
+        return CAIRO_FORMAT_ARGB32;
+    case QImage::Format_RGB32:
+        return CAIRO_FORMAT_RGB24;
+    case QImage::Format_Indexed8: // XXX not quite
+        return CAIRO_FORMAT_A8;
+#ifdef WORDS_BIGENDIAN
+    case QImage::Format_Mono:
+#else
+    case QImage::Format_MonoLSB:
+#endif
+        return CAIRO_FORMAT_A1;
+    default:
+        return CAIRO_FORMAT_A1;
+    }
+
+    return CAIRO_FORMAT_A1;
+}
+
+static QImage::Format
+_qimage_format_from_cairo_format (cairo_format_t fmt)
+{
+    switch (fmt) {
+    case CAIRO_FORMAT_ARGB32:
+        return QImage::Format_ARGB32_Premultiplied;
+    case CAIRO_FORMAT_RGB24:
+        return QImage::Format_RGB32;
+    case CAIRO_FORMAT_A8:
+        return QImage::Format_Indexed8; // XXX not quite
+    case CAIRO_FORMAT_A1:
+#ifdef WORDS_BIGENDIAN
+        return QImage::Format_Mono; // XXX think we need to choose between this and LSB
+#else
+        return QImage::Format_MonoLSB;
+#endif
+    }
+
+    return QImage::Format_Mono;
+}
+
+static inline QMatrix
+_qmatrix_from_cairo_matrix (const cairo_matrix_t& m)
+{
+    return QMatrix(m.xx, m.yx, m.xy, m.yy, m.x0, m.y0);
+}
+
+static inline void
+_qmatrix_from_cairo_matrix (const cairo_matrix_t& m, QMatrix& qm)
+{
+    qm.setMatrix(m.xx, m.yx, m.xy, m.yy, m.x0, m.y0);
+}
+
+/** Path conversion **/
+typedef struct _qpainter_path_transform {
+    QPainterPath *path;
+    cairo_matrix_t *ctm_inverse;
+} qpainter_path_data;
+
+/* cairo path -> execute in context */
+static cairo_status_t
+_cairo_path_to_qpainterpath_move_to (void *closure, cairo_point_t *point)
+{
+    qpainter_path_data *pdata = (qpainter_path_data *)closure;
+    double x = _cairo_fixed_to_double (point->x);
+    double y = _cairo_fixed_to_double (point->y);
+
+    if (pdata->ctm_inverse)
+        cairo_matrix_transform_point (pdata->ctm_inverse, &x, &y);
+
+    DP(fprintf(stderr, "moveto %4.2f %4.2f\n", x, y));
+
+    pdata->path->moveTo(x, y);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_path_to_qpainterpath_line_to (void *closure, cairo_point_t *point)
+{
+    qpainter_path_data *pdata = (qpainter_path_data *)closure;
+    double x = _cairo_fixed_to_double (point->x);
+    double y = _cairo_fixed_to_double (point->y);
+
+    if (pdata->ctm_inverse)
+        cairo_matrix_transform_point (pdata->ctm_inverse, &x, &y);
+
+    pdata->path->lineTo(x, y);
+
+    if (pdata->path->isEmpty())
+        pdata->path->moveTo(x, y);
+    else
+        pdata->path->lineTo(x, y);
+
+    DP(fprintf(stderr, "lineto %4.2f %4.2f\n", x, y));
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_path_to_qpainterpath_curve_to (void *closure, cairo_point_t *p0, cairo_point_t *p1, cairo_point_t *p2)
+{
+    qpainter_path_data *pdata = (qpainter_path_data *)closure;
+    double x0 = _cairo_fixed_to_double (p0->x);
+    double y0 = _cairo_fixed_to_double (p0->y);
+    double x1 = _cairo_fixed_to_double (p1->x);
+    double y1 = _cairo_fixed_to_double (p1->y);
+    double x2 = _cairo_fixed_to_double (p2->x);
+    double y2 = _cairo_fixed_to_double (p2->y);
+
+    if (pdata->ctm_inverse) {
+        cairo_matrix_transform_point (pdata->ctm_inverse, &x0, &y0);
+        cairo_matrix_transform_point (pdata->ctm_inverse, &x1, &y1);
+        cairo_matrix_transform_point (pdata->ctm_inverse, &x2, &y2);
+    }
+
+    pdata->path->cubicTo (x0, y0, x1, y1, x2, y2);
+
+    DP(fprintf(stderr, "curveto %f %f %f %f %f %f\n", x0, y0, x1, y1, x2, y2));
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_path_to_qpainterpath_close_path (void *closure)
+{
+    qpainter_path_data *pdata = (qpainter_path_data *)closure;
+
+    pdata->path->closeSubpath();
+
+    DP(fprintf(stderr, "closepath\n"));
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_quartz_cairo_path_to_qpainterpath (cairo_path_fixed_t *path,
+                                          QPainterPath *qpath,
+                                          cairo_fill_rule_t fill_rule,
+                                          cairo_matrix_t *ctm_inverse = NULL)
+{
+    qpainter_path_data pdata = { qpath, ctm_inverse };
+
+    qpath->setFillRule (fill_rule == CAIRO_FILL_RULE_WINDING ? Qt::WindingFill : Qt::OddEvenFill);
+
+    return _cairo_path_fixed_interpret (path,
+                                        CAIRO_DIRECTION_FORWARD,
+                                        _cairo_path_to_qpainterpath_move_to,
+                                        _cairo_path_to_qpainterpath_line_to,
+                                        _cairo_path_to_qpainterpath_curve_to,
+                                        _cairo_path_to_qpainterpath_close_path,
+                                        &pdata);
+}
+
+static cairo_status_t
+_cairo_quartz_cairo_path_to_qpainterpath (cairo_path_fixed_t *path,
+        QPainterPath *qpath,
+        cairo_matrix_t *ctm_inverse)
+{
+    return _cairo_quartz_cairo_path_to_qpainterpath (path, qpath,
+            CAIRO_FILL_RULE_WINDING,
+            ctm_inverse);
+}
+
+/**
+ ** Surface backend methods
+ **/
+static cairo_surface_t *
+_cairo_qpainter_surface_create_similar (void *abstract_surface,
+                                        cairo_content_t content,
+                                        int width,
+                                        int height)
+{
+    cairo_qpainter_surface_t *qs = (cairo_qpainter_surface_t *) abstract_surface;
+
+    cairo_bool_t do_image = qs->image != NULL;
+
+    D(fprintf(stderr, "q[%p] create_similar: %d %d [%d] -> ", abstract_surface, width, height, content));
+
+    if (!do_image && (!_qpixmaps_have_no_alpha || content == CAIRO_CONTENT_COLOR)) {
+	cairo_surface_t *result =
+	    cairo_qpainter_surface_create_with_qpixmap (content, width, height);
+
+	if (cairo_surface_get_content (result) == content) {
+	    D(fprintf(stderr, "qpixmap content: %d\n", content));
+	    return result;
+	}
+
+	_qpixmaps_have_no_alpha = TRUE;
+	cairo_surface_destroy (result);
+    }
+
+    D(fprintf (stderr, "qimage\n"));
+    return cairo_qpainter_surface_create_with_qimage
+	(_cairo_format_from_content (content), width, height);
+}
+
+static cairo_status_t
+_cairo_qpainter_surface_finish (void *abstract_surface)
+{
+    cairo_qpainter_surface_t *qs = (cairo_qpainter_surface_t *) abstract_surface;
+
+    D(fprintf(stderr, "q[%p] finish\n", abstract_surface));
+
+    /* Only delete p if we created it */
+    if (qs->image || qs->pixmap)
+        delete qs->p;
+    else
+        qs->p->restore();
+
+    if (qs->image_equiv)
+        cairo_surface_destroy ((cairo_surface_t*) qs->image_equiv);
+
+#if defined(Q_WS_X11) && defined(CAIRO_HAS_XLIB_XRENDER_SURFACE)
+    if (qs->xlib_equiv)
+        cairo_surface_destroy (qs->xlib_equiv);
+#endif
+
+    if (qs->image)
+        delete qs->image;
+
+    if (qs->pixmap)
+        delete qs->pixmap;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_qpainter_surface_acquire_source_image (void *abstract_surface,
+                                              cairo_image_surface_t **image_out,
+                                              void **image_extra)
+{
+    cairo_qpainter_surface_t *qs = (cairo_qpainter_surface_t *) abstract_surface;
+
+    D(fprintf(stderr, "q[%p] acquire_source_image\n", abstract_surface));
+
+    *image_extra = NULL;
+
+    if (qs->image_equiv) {
+        *image_out = (cairo_image_surface_t*)
+                     cairo_surface_reference ((cairo_surface_t*) qs->image_equiv);
+
+        return CAIRO_STATUS_SUCCESS;
+    }
+
+    if (qs->pixmap) {
+        QImage *qimg = new QImage(qs->pixmap->toImage());
+
+        *image_out = (cairo_image_surface_t*)
+                     cairo_image_surface_create_for_data (qimg->bits(),
+                                                          _cairo_format_from_qimage_format (qimg->format()),
+                                                          qimg->width(), qimg->height(),
+                                                          qimg->bytesPerLine());
+        *image_extra = qimg;
+
+        return CAIRO_STATUS_SUCCESS;
+    }
+
+    return CAIRO_STATUS_NO_MEMORY;
+}
+
+static void
+_cairo_qpainter_surface_release_source_image (void *abstract_surface,
+                                              cairo_image_surface_t *image,
+                                              void *image_extra)
+{
+    //cairo_qpainter_surface_t *qs = (cairo_qpainter_surface_t *) abstract_surface;
+
+    D(fprintf(stderr, "q[%p] release_source_image\n", abstract_surface));
+
+    cairo_surface_destroy ((cairo_surface_t*) image);
+
+    if (image_extra) {
+        QImage *qimg = (QImage *) image_extra;
+        delete qimg;
+    }
+}
+
+static cairo_status_t
+_cairo_qpainter_surface_acquire_dest_image (void *abstract_surface,
+                                            cairo_rectangle_int_t *interest_rect,
+                                            cairo_image_surface_t **image_out,
+                                            cairo_rectangle_int_t *image_rect,
+                                            void **image_extra)
+{
+    cairo_qpainter_surface_t *qs = (cairo_qpainter_surface_t *) abstract_surface;
+    QImage *qimg = NULL;
+
+    D(fprintf(stderr, "q[%p] acquire_dest_image\n", abstract_surface));
+
+    *image_extra = NULL;
+
+    if (qs->image_equiv) {
+        *image_out = (cairo_image_surface_t*)
+                     cairo_surface_reference ((cairo_surface_t*) qs->image_equiv);
+
+        image_rect->x = qs->window.x();
+        image_rect->y = qs->window.y();
+        image_rect->width = qs->window.width();
+        image_rect->height = qs->window.height();
+
+        return CAIRO_STATUS_SUCCESS;
+    }
+
+    QPoint offset;
+
+    if (qs->pixmap) {
+        qimg = new QImage(qs->pixmap->toImage());
+    } else {
+        // Try to figure out what kind of QPaintDevice we have, and
+        // how we can grab an image from it
+        QPaintDevice *pd = qs->p->device();
+	if (!pd)
+	    return CAIRO_STATUS_NO_MEMORY;
+
+	QPaintDevice *rpd = QPainter::redirected(pd, &offset);
+	if (rpd)
+	    pd = rpd;
+
+        if (pd->devType() == QInternal::Image) {
+            qimg = new QImage(((QImage*) pd)->copy());
+        } else if (pd->devType() == QInternal::Pixmap) {
+            qimg = new QImage(((QPixmap*) pd)->toImage());
+        } else if (pd->devType() == QInternal::Widget) {
+            qimg = new QImage(QPixmap::grabWindow(((QWidget*)pd)->winId()).toImage());
+        }
+    }
+
+    if (qimg == NULL)
+        return CAIRO_STATUS_NO_MEMORY;
+
+    *image_out = (cairo_image_surface_t*)
+                 cairo_image_surface_create_for_data (qimg->bits(),
+                                                      _cairo_format_from_qimage_format (qimg->format()),
+                                                      qimg->width(), qimg->height(),
+                                                      qimg->bytesPerLine());
+    *image_extra = qimg;
+
+    image_rect->x = qs->window.x() + offset.x();
+    image_rect->y = qs->window.y() + offset.y();
+    image_rect->width = qs->window.width() - offset.x();
+    image_rect->height = qs->window.height() - offset.y();
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_qpainter_surface_release_dest_image (void *abstract_surface,
+        cairo_rectangle_int_t *interest_rect,
+        cairo_image_surface_t *image,
+        cairo_rectangle_int_t *image_rect,
+        void *image_extra)
+{
+    cairo_qpainter_surface_t *qs = (cairo_qpainter_surface_t *) abstract_surface;
+    D(fprintf(stderr, "q[%p] release_dest_image\n", abstract_surface));
+
+    cairo_surface_destroy ((cairo_surface_t*) image);
+
+    if (image_extra) {
+        QImage *qimg = (QImage*) image_extra;
+
+        // XXX should I be using setBackgroundMode here instead of setCompositionMode?
+        if (qs->supports_porter_duff)
+            qs->p->setCompositionMode (QPainter::CompositionMode_Source);
+
+        qs->p->drawImage (image_rect->x, image_rect->y, *qimg);
+
+        if (qs->supports_porter_duff)
+            qs->p->setCompositionMode (QPainter::CompositionMode_SourceOver);
+
+        delete qimg;
+    }
+}
+
+static cairo_status_t
+_cairo_qpainter_surface_clone_similar (void *abstract_surface,
+                                       cairo_surface_t *src,
+                                       int              src_x,
+                                       int              src_y,
+                                       int              width,
+                                       int              height,
+                                       cairo_surface_t **clone_out)
+{
+    cairo_qpainter_surface_t *qs = (cairo_qpainter_surface_t *) abstract_surface;
+    cairo_surface_t *new_surf = NULL;
+
+    // For non-image targets, always try to create a QPixmap first
+    if (qs->image == NULL && (!_qpixmaps_have_no_alpha || src->content == CAIRO_CONTENT_COLOR))
+    {
+        new_surf = cairo_qpainter_surface_create_with_qpixmap
+	    (src->content, width, height);
+	if (cairo_surface_get_content (new_surf) != src->content) {
+	    cairo_surface_destroy (new_surf);
+	    _qpixmaps_have_no_alpha = TRUE;
+	    new_surf = NULL;
+	}
+    }
+
+    if (new_surf == NULL) {
+        new_surf = cairo_qpainter_surface_create_with_qimage
+                   (_cairo_format_from_content (src->content), width, height);
+    }
+
+    if (new_surf->status)
+        return new_surf->status;
+
+    cairo_pattern_union_t upat;
+    _cairo_pattern_init_for_surface (&upat.surface, src);
+
+    cairo_matrix_t tx;
+    cairo_matrix_init_translate (&tx, -src_x, -src_y);
+    cairo_pattern_set_matrix (&upat.base, &tx);
+
+    cairo_int_status_t status =
+        _cairo_qpainter_surface_paint (new_surf, CAIRO_OPERATOR_SOURCE, &upat.base);
+
+    _cairo_pattern_fini (&upat.base);
+
+    if (status) {
+        cairo_surface_destroy (new_surf);
+        new_surf = NULL;
+    }
+
+    *clone_out = new_surf;
+    return (cairo_status_t) status;
+}
+
+static cairo_int_status_t
+_cairo_qpainter_surface_get_extents (void *abstract_surface,
+                                     cairo_rectangle_int_t *extents)
+{
+    cairo_qpainter_surface_t *qs = (cairo_qpainter_surface_t *) abstract_surface;
+
+    extents->x = qs->window.x();
+    extents->y = qs->window.y();
+    extents->width = qs->window.width();
+    extents->height = qs->window.height();
+
+    return CAIRO_INT_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_qpainter_surface_intersect_clip_path (void *abstract_surface,
+					     cairo_path_fixed_t *path,
+					     cairo_fill_rule_t fill_rule,
+					     double tolerance,
+					     cairo_antialias_t antialias)
+{
+    cairo_qpainter_surface_t *qs = (cairo_qpainter_surface_t *) abstract_surface;
+
+    D(fprintf(stderr, "q[%p] intersect_clip_path %s\n", abstract_surface, path ? "(path)" : "(clear)"));
+
+    if (!qs->p)
+        return CAIRO_INT_STATUS_SUCCESS;
+
+    if (path == NULL) {
+	//fprintf (stderr, "clip clear\n");
+        // How the clip path is reset depends on whether we own p or not
+        if (qs->pixmap || qs->image) {
+            // we own p
+            qs->p->setClipping (false);
+        } else {
+            qs->p->restore ();
+            qs->p->save ();
+        }
+
+	if (!qs->no_update_clip_bounds) {
+	    qs->clip_bounds.setRect(0, 0, 0, 0);
+	    qs->has_clipping = false;
+	}
+
+        return CAIRO_INT_STATUS_SUCCESS;
+    }
+
+    // Qt will implicity enable clipping, and will use ReplaceClip
+    // instead of IntersectClip if clipping was disabled before
+
+    // Note: Qt is really bad at dealing with clip paths.  It doesn't
+    // seem to usefully recognize rectangular paths, instead going down
+    // extremely slow paths whenever a clip path is set.  So,
+    // we do a bunch of work here to try to get rectangles or regions
+    // down to Qt for clipping.
+
+    tstart();
+
+    QRect clip_bounds;
+
+    // First check if it's an integer-aligned single rectangle
+    cairo_box_t box;
+    if (_cairo_path_fixed_is_box (path, &box) &&
+	_cairo_fixed_is_integer (box.p1.x) &&
+	_cairo_fixed_is_integer (box.p1.y) &&
+	_cairo_fixed_is_integer (box.p2.x) &&
+	_cairo_fixed_is_integer (box.p2.y))
+    {
+	QRect r(_cairo_fixed_integer_part(box.p1.x),
+		_cairo_fixed_integer_part(box.p1.y),
+		_cairo_fixed_integer_part(box.p2.x - box.p1.x),
+		_cairo_fixed_integer_part(box.p2.y - box.p1.y));
+
+	r = r.normalized();
+
+	DP(fprintf (stderr, "clip rect: %d %d %d %d\n", r.x(), r.y(), r.width(), r.height()));
+
+	clip_bounds = r;
+
+	qs->p->setClipRect (r, Qt::IntersectClip);
+    } else {
+	// Then if it's not an integer-aligned rectangle, check
+	// if we can extract a region (a set of rectangles) out.
+	// We use cairo to convert the path to traps.
+
+	cairo_traps_t traps;
+	cairo_int_status_t status;
+	cairo_region_t region;
+
+	_cairo_traps_init (&traps);
+	status = (cairo_int_status_t)
+	    _cairo_path_fixed_fill_to_traps (path, fill_rule, tolerance, &traps);
+	if (status) {
+	    _cairo_traps_fini (&traps);
+	    return status;
+	}
+
+	status = _cairo_traps_extract_region (&traps, &region);
+	_cairo_traps_fini (&traps);
+
+	if (status == CAIRO_INT_STATUS_SUCCESS) {
+	    cairo_box_int_t *boxes;
+	    int n_boxes;
+
+	    QRegion qr;
+
+	    _cairo_region_get_boxes (&region, &n_boxes, &boxes);
+
+	    for (int i = 0; i < n_boxes; i++) {
+		QRect r(boxes[i].p1.x,
+			boxes[i].p1.y,
+			boxes[i].p2.x - boxes[i].p1.x,
+			boxes[i].p2.y - boxes[i].p1.y);
+
+		if (i == 0)
+		    clip_bounds = r;
+		else
+		    clip_bounds = clip_bounds.united(r);
+
+		qr = qr.unite(r);
+	    }
+
+	    _cairo_region_boxes_fini (&region, boxes);
+	    _cairo_region_fini (&region);
+
+	    qs->p->setClipRegion (qr, Qt::IntersectClip);
+	} else {
+	    // We weren't able to extract a region from the traps.
+	    // Just hand the path down to QPainter.
+	    QPainterPath qpath;
+
+	    if (_cairo_quartz_cairo_path_to_qpainterpath (path, &qpath, fill_rule) != CAIRO_STATUS_SUCCESS)
+		return CAIRO_INT_STATUS_UNSUPPORTED;
+
+	    clip_bounds = qpath.boundingRect().toAlignedRect();
+
+	    // XXX Antialiasing is ignored
+	    qs->p->setClipPath (qpath, Qt::IntersectClip);
+	}
+    }
+
+    if (!qs->no_update_clip_bounds) {
+	clip_bounds = qs->p->worldTransform().mapRect(clip_bounds);
+
+	if (qs->has_clipping) {
+	    qs->clip_bounds = qs->clip_bounds.intersect(clip_bounds);
+	} else {
+	    qs->clip_bounds = clip_bounds;
+	    qs->has_clipping = true;
+	}
+    }
+
+    tend("clip");
+
+    return CAIRO_INT_STATUS_SUCCESS;
+}
+
+/**
+ ** Brush conversion
+ **/
+
+struct PatternToBrushConverter {
+    PatternToBrushConverter (cairo_pattern_t *pattern)
+      : mBrush(0),
+	mAcquiredImageParent(0)
+    {
+	if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
+	    cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) pattern;
+	    QColor color;
+	    color.setRgbF(solid->color.red,
+			  solid->color.green,
+			  solid->color.blue,
+			  solid->color.alpha);
+
+	    mBrush = new QBrush(color);
+	} else if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
+	    cairo_surface_pattern_t *spattern = (cairo_surface_pattern_t*) pattern;
+	    cairo_surface_t *surface = spattern->surface;
+
+	    if (surface->type == CAIRO_SURFACE_TYPE_QPAINTER) {
+		cairo_qpainter_surface_t *qs = (cairo_qpainter_surface_t*) surface;
+
+		if (qs->image) {
+		    mBrush = new QBrush(*qs->image);
+		} else if (qs->pixmap) {
+		    mBrush = new QBrush(*qs->pixmap);
+		} else {
+		    // do something smart
+		    mBrush = new QBrush(0xff0000ff);
+		}
+	    } else {
+		cairo_image_surface_t *isurf = NULL;
+
+		if (surface->type == CAIRO_SURFACE_TYPE_IMAGE) {
+		    isurf = (cairo_image_surface_t*) surface;
+		} else {
+		    void *image_extra;
+
+		    if (_cairo_surface_acquire_source_image (surface, &isurf, &image_extra) == CAIRO_STATUS_SUCCESS) {
+			mAcquiredImageParent = surface;
+			mAcquiredImage = isurf;
+			mAcquiredImageExtra = image_extra;
+		    } else {
+			isurf = NULL;
+		    }
+		}
+
+		if (isurf) {
+		    mBrush = new QBrush (QImage ((const uchar *) isurf->data,
+						 isurf->width,
+						 isurf->height,
+						 isurf->stride,
+						 _qimage_format_from_cairo_format (isurf->format)));
+		} else {
+		    mBrush = new QBrush(0x0000ffff);
+		}
+	    }
+	} else if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
+		   pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
+	{
+	    QGradient *grad;
+	    cairo_bool_t reverse_stops = FALSE;
+	    cairo_bool_t emulate_reflect = FALSE;
+	    double offset = 0.0;
+
+	    cairo_extend_t extend = pattern->extend;
+
+	    cairo_gradient_pattern_t *gpat = (cairo_gradient_pattern_t *) pattern;
+
+	    if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR) {
+		cairo_linear_pattern_t *lpat = (cairo_linear_pattern_t *) pattern;
+		grad = new QLinearGradient (_cairo_fixed_to_double (lpat->p1.x),
+					    _cairo_fixed_to_double (lpat->p1.y),
+					    _cairo_fixed_to_double (lpat->p2.x),
+					    _cairo_fixed_to_double (lpat->p2.y));
+	    } else if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) {
+		cairo_radial_pattern_t *rpat = (cairo_radial_pattern_t *) pattern;
+
+		/* Based on the SVG surface code */
+
+		cairo_point_t *c0, *c1;
+		cairo_fixed_t radius0, radius1;
+
+		if (rpat->r1 < rpat->r2) {
+		    c0 = &rpat->c1;
+		    c1 = &rpat->c2;
+		    radius0 = rpat->r1;
+		    radius1 = rpat->r2;
+		    reverse_stops = FALSE;
+		} else {
+		    c0 = &rpat->c2;
+		    c1 = &rpat->c1;
+		    radius0 = rpat->r2;
+		    radius1 = rpat->r1;
+		    reverse_stops = TRUE;
+		}
+
+		double x0 = _cairo_fixed_to_double (c0->x);
+		double y0 = _cairo_fixed_to_double (c0->y);
+		double r0 = _cairo_fixed_to_double (radius0);
+		double x1 = _cairo_fixed_to_double (c1->x);
+		double y1 = _cairo_fixed_to_double (c1->y);
+		double r1 = _cairo_fixed_to_double (radius1);
+
+		if (rpat->r1 == rpat->r2) {
+		    grad = new QRadialGradient (x1, y1, r1, x1, y1);
+		} else {
+		    double fx = (r1 * x0 - r0 * x1) / (r1 - r0);
+		    double fy = (r1 * y0 - r0 * y1) / (r1 - r0);
+
+		    /* QPainter doesn't support the inner circle and use instead a gradient focal.
+		     * That means we need to emulate the cairo behaviour by processing the
+		     * cairo gradient stops.
+		     * The CAIRO_EXTENT_NONE and CAIRO_EXTENT_PAD modes are quite easy to handle,
+		     * it's just a matter of stop position translation and calculation of
+		     * the corresponding SVG radial gradient focal.
+		     * The CAIRO_EXTENT_REFLECT and CAIRO_EXTEND_REPEAT modes require to compute a new
+		     * radial gradient, with an new outer circle, equal to r1 - r0 in the CAIRO_EXTEND_REPEAT
+		     * case, and 2 * (r1 - r0) in the CAIRO_EXTENT_REFLECT case, and a new gradient stop
+		     * list that maps to the original cairo stop list.
+		     */
+		    if ((extend == CAIRO_EXTEND_REFLECT || extend == CAIRO_EXTEND_REPEAT) && r0 > 0.0) {
+			double r_org = r1;
+			double r, x, y;
+
+			if (extend == CAIRO_EXTEND_REFLECT) {
+			    r1 = 2 * r1 - r0;
+			    emulate_reflect = TRUE;
+			}
+
+			offset = fmod (r1, r1 - r0) / (r1 - r0) - 1.0;
+			r = r1 - r0;
+
+			/* New position of outer circle. */
+			x = r * (x1 - fx) / r_org + fx;
+			y = r * (y1 - fy) / r_org + fy;
+
+			x1 = x;
+			y1 = y;
+			r1 = r;
+			r0 = 0.0;
+		    } else {
+			offset = r0 / r1;
+		    }
+
+		    grad = new QRadialGradient (x1, y1, r1, fx, fy);
+
+		    if (extend == CAIRO_EXTEND_NONE && r0 != 0.0)
+			grad->setColorAt (r0 / r1, Qt::transparent);
+		}
+	    }
+
+	    switch (extend) {
+		case CAIRO_EXTEND_NONE:
+		case CAIRO_EXTEND_PAD:
+		    grad->setSpread(QGradient::PadSpread);
+
+		    grad->setColorAt (0.0, Qt::transparent);
+		    grad->setColorAt (1.0, Qt::transparent);
+		    break;
+
+		case CAIRO_EXTEND_REFLECT:
+		    grad->setSpread(QGradient::ReflectSpread);
+		    break;
+
+		case CAIRO_EXTEND_REPEAT:
+		    grad->setSpread(QGradient::RepeatSpread);
+		    break;
+	    }
+
+	    for (unsigned int i = 0; i < gpat->n_stops; i++) {
+		int index = i;
+		if (reverse_stops)
+		    index = gpat->n_stops - i - 1;
+
+		double offset = gpat->stops[i].offset;
+		QColor color;
+		color.setRgbF(gpat->stops[i].color.red,
+			      gpat->stops[i].color.green,
+			      gpat->stops[i].color.blue,
+			      gpat->stops[i].color.alpha);
+
+		if (emulate_reflect) {
+		    offset = offset / 2.0;
+		    grad->setColorAt (1.0 - offset, color);
+		}
+
+		grad->setColorAt (offset, color);
+	    }
+
+	    mBrush = new QBrush(*grad);
+
+	    delete grad;
+ 	}
+
+	if (mBrush &&
+            pattern->type != CAIRO_PATTERN_TYPE_SOLID &&
+            !_cairo_matrix_is_identity(&pattern->matrix))
+	{
+	    cairo_matrix_t pm = pattern->matrix;
+	    if (cairo_matrix_invert (&pm) == CAIRO_STATUS_SUCCESS)
+		mBrush->setMatrix(_qmatrix_from_cairo_matrix (pm));
+	}
+    }
+
+    ~PatternToBrushConverter () {
+	delete mBrush;
+
+	if (mAcquiredImageParent)
+	    _cairo_surface_release_source_image (mAcquiredImageParent, mAcquiredImage, mAcquiredImageExtra);
+    }
+
+    operator QBrush& () {
+	return *mBrush;
+    }
+
+    QBrush *mBrush;
+
+    cairo_surface_t *mAcquiredImageParent;
+    cairo_image_surface_t *mAcquiredImage;
+    void *mAcquiredImageExtra;
+};
+
+struct PatternToPenConverter {
+    PatternToPenConverter (cairo_pattern_t *source,
+			   cairo_stroke_style_t *style)
+      : mBrushConverter(source)
+    {
+	Qt::PenJoinStyle join = Qt::MiterJoin;
+	Qt::PenCapStyle cap = Qt::SquareCap;
+
+	switch (style->line_cap) {
+	    case CAIRO_LINE_CAP_BUTT:
+		cap = Qt::FlatCap;
+		break;
+	    case CAIRO_LINE_CAP_ROUND:
+		cap = Qt::RoundCap;
+		break;
+	    case CAIRO_LINE_CAP_SQUARE:
+		cap = Qt::SquareCap;
+		break;
+	}
+
+	switch (style->line_join) {
+	    case CAIRO_LINE_JOIN_MITER:
+		join = Qt::MiterJoin;
+		break;
+	    case CAIRO_LINE_JOIN_ROUND:
+		join = Qt::RoundJoin;
+		break;
+	    case CAIRO_LINE_JOIN_BEVEL:
+		join = Qt::BevelJoin;
+		break;
+	}
+
+	mPen = new QPen (mBrushConverter, style->line_width, Qt::SolidLine, cap, join);
+	mPen->setMiterLimit (style->miter_limit);
+
+	if (style->dash && style->num_dashes) {
+	    unsigned int odd_dash = style->num_dashes % 2;
+
+	    QVector<qreal> dashes (odd_dash ? style->num_dashes * 2 : style->num_dashes);
+	    for (unsigned int i = 0; i < odd_dash+1; i++) {
+		for (unsigned int j = 0; j < style->num_dashes; j++) {
+		    // In Qt, the dash lengths are given in units of line width, whereas
+		    // in cairo, they are in user-space units.  We'll always apply the CTM,
+		    // so all we have to do here is divide cairo's dash lengths by the line
+		    // width.
+		    dashes.append (style->dash[j] / style->line_width);
+		}
+	    }
+
+	    mPen->setDashPattern (dashes);
+	    mPen->setDashOffset (style->dash_offset / style->line_width);
+	}
+    }
+
+    ~PatternToPenConverter() {
+	delete mPen;
+    }
+
+    operator QPen& () {
+	return *mPen;
+    }
+
+    QPen *mPen;
+    PatternToBrushConverter mBrushConverter;
+};
+
+/**
+ ** Core drawing operations
+ **/
+
+bool
+_cairo_qpainter_fast_fill (cairo_qpainter_surface_t *qs,
+			   cairo_pattern_t *source,
+			   cairo_path_fixed_t *path = NULL,
+			   cairo_fill_rule_t fill_rule = CAIRO_FILL_RULE_WINDING,
+			   double tolerance = 0.0,
+			   cairo_antialias_t antialias = CAIRO_ANTIALIAS_NONE)
+{
+    QImage *qsSrc_image = NULL;
+    QPixmap *qsSrc_pixmap = NULL;
+    std::auto_ptr<QImage> qsSrc_image_d;
+
+    if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
+	cairo_surface_pattern_t *spattern = (cairo_surface_pattern_t*) source;
+	if (spattern->surface->type == CAIRO_SURFACE_TYPE_QPAINTER) {
+	    cairo_qpainter_surface_t *p = (cairo_qpainter_surface_t*) spattern->surface;
+
+	    qsSrc_image = p->image;
+	    qsSrc_pixmap = p->pixmap;
+	} else if (spattern->surface->type == CAIRO_SURFACE_TYPE_IMAGE) {
+	    cairo_image_surface_t *p = (cairo_image_surface_t*) spattern->surface;
+	    qsSrc_image = new QImage((const uchar*) p->data,
+				     p->width,
+				     p->height,
+				     p->stride,
+				     _qimage_format_from_cairo_format(p->format));
+	    qsSrc_image_d.reset(qsSrc_image);
+	}
+    }
+
+    if (!qsSrc_image && !qsSrc_pixmap)
+	return false;
+
+    // We can only drawTiledPixmap; there's no drawTiledImage
+    if (!qsSrc_pixmap && (source->extend == CAIRO_EXTEND_REPEAT || source->extend == CAIRO_EXTEND_REFLECT))
+	return false;
+
+    QMatrix sourceMatrix = _qmatrix_from_cairo_matrix (source->matrix);
+    cairo_int_status_t status;
+
+    // We can draw this faster by clipping and calling drawImage/drawPixmap.
+    // Use our own clipping function so that we can get the
+    // region handling to end up with the fastest possible clip.
+    //
+    // XXX Antialiasing will fail pretty hard here, since we can't clip with AA
+    // with QPainter.
+    qs->p->save();
+
+    if (path) {
+	qs->no_update_clip_bounds = true;
+	status = _cairo_qpainter_surface_intersect_clip_path (qs, path, fill_rule, tolerance, antialias);
+	qs->no_update_clip_bounds = false;
+
+	if (status != CAIRO_INT_STATUS_SUCCESS) {
+	    qs->p->restore();
+	    return false;
+	}
+    }
+
+    qs->p->setWorldMatrix (sourceMatrix.inverted(), true);
+
+    switch (source->extend) {
+    case CAIRO_EXTEND_REPEAT:
+    // XXX handle reflect by tiling 4 times first
+    case CAIRO_EXTEND_REFLECT: {
+	assert (qsSrc_pixmap);
+
+	// Render the tiling to cover the entire destination window (because
+	// it'll be clipped).  Transform the window rect by the inverse
+	// of the current world transform so that the device coordinates
+	// end up as the right thing.
+	QRectF dest = qs->p->worldTransform().inverted().mapRect(QRectF(qs->window));
+	QPointF origin = sourceMatrix.map(QPointF(0.0, 0.0));
+
+	qs->p->drawTiledPixmap (dest, *qsSrc_pixmap, origin);
+    }
+	break;
+    case CAIRO_EXTEND_NONE:
+    case CAIRO_EXTEND_PAD: // XXX not exactly right, but good enough
+    default:
+	if (qsSrc_image)
+	    qs->p->drawImage (0, 0, *qsSrc_image);
+	else if (qsSrc_pixmap)
+	    qs->p->drawPixmap (0, 0, *qsSrc_pixmap);
+	break;
+    }
+
+    qs->p->restore();
+
+    return true;
+}
+
+cairo_int_status_t
+_cairo_qpainter_surface_paint (void *abstract_surface,
+                               cairo_operator_t op,
+                               cairo_pattern_t *source)
+{
+    cairo_qpainter_surface_t *qs = (cairo_qpainter_surface_t *) abstract_surface;
+
+    D(fprintf(stderr, "q[%p] paint op:%s\n", abstract_surface, _opstr(op)));
+
+    if (!qs->p)
+        return CAIRO_INT_STATUS_SUCCESS;
+
+    if (qs->supports_porter_duff)
+        qs->p->setCompositionMode (_qpainter_compositionmode_from_cairo_op (op));
+
+    bool success = _cairo_qpainter_fast_fill (qs, source);
+
+    if (!success) {
+	PatternToBrushConverter brush(source);
+        qs->p->fillRect (qs->window, brush);
+    }
+
+    if (qs->supports_porter_duff)
+        qs->p->setCompositionMode (QPainter::CompositionMode_SourceOver);
+
+    return CAIRO_INT_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_qpainter_surface_fill (void *abstract_surface,
+                              cairo_operator_t op,
+                              cairo_pattern_t *source,
+                              cairo_path_fixed_t *path,
+                              cairo_fill_rule_t fill_rule,
+                              double tolerance,
+                              cairo_antialias_t antialias)
+{
+    cairo_qpainter_surface_t *qs = (cairo_qpainter_surface_t *) abstract_surface;
+
+    D(fprintf(stderr, "q[%p] fill op:%s\n", abstract_surface, _opstr(op)));
+
+    if (!qs->p)
+        return CAIRO_INT_STATUS_SUCCESS;
+
+    tstart();
+
+    if (qs->supports_porter_duff)
+        qs->p->setCompositionMode (_qpainter_compositionmode_from_cairo_op (op));
+
+    // XXX Qt4.3, 4.4 misrenders some complex paths if antialiasing is
+    // enabled
+    //qs->p->setRenderHint (QPainter::Antialiasing, antialias == CAIRO_ANTIALIAS_NONE ? false : true);
+    qs->p->setRenderHint (QPainter::SmoothPixmapTransform, source->filter != CAIRO_FILTER_FAST);
+
+    bool success = _cairo_qpainter_fast_fill (qs, source, path, fill_rule, tolerance, antialias);
+
+    if (!success) {
+	QPainterPath qpath;
+	if (_cairo_quartz_cairo_path_to_qpainterpath (path, &qpath, fill_rule) != CAIRO_STATUS_SUCCESS)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+
+	PatternToBrushConverter brush(source);
+	qs->p->fillPath (qpath, brush);
+    }
+
+    if (qs->supports_porter_duff)
+        qs->p->setCompositionMode (QPainter::CompositionMode_SourceOver);
+
+    tend("fill");
+
+    return CAIRO_INT_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_qpainter_surface_stroke (void *abstract_surface,
+                                cairo_operator_t op,
+                                cairo_pattern_t *source,
+                                cairo_path_fixed_t *path,
+                                cairo_stroke_style_t *style,
+                                cairo_matrix_t *ctm,
+                                cairo_matrix_t *ctm_inverse,
+                                double tolerance,
+                                cairo_antialias_t antialias)
+{
+    cairo_qpainter_surface_t *qs = (cairo_qpainter_surface_t *) abstract_surface;
+
+    D(fprintf(stderr, "q[%p] stroke op:%s\n", abstract_surface, _opstr(op)));
+
+    if (!qs->p)
+        return CAIRO_INT_STATUS_SUCCESS;
+
+    QPainterPath qpath;
+    if (_cairo_quartz_cairo_path_to_qpainterpath (path, &qpath, ctm_inverse) != CAIRO_STATUS_SUCCESS)
+        return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    QMatrix savedMatrix = qs->p->worldMatrix();
+
+    if (qs->supports_porter_duff)
+        qs->p->setCompositionMode (_qpainter_compositionmode_from_cairo_op (op));
+
+    qs->p->setWorldMatrix (_qmatrix_from_cairo_matrix (*ctm), true);
+    // XXX Qt4.3, 4.4 misrenders some complex paths if antialiasing is
+    // enabled
+    //qs->p->setRenderHint (QPainter::Antialiasing, antialias == CAIRO_ANTIALIAS_NONE ? false : true);
+    qs->p->setRenderHint (QPainter::SmoothPixmapTransform, source->filter != CAIRO_FILTER_FAST);
+
+    PatternToPenConverter pen(source, style);
+
+    qs->p->setPen(pen);
+    qs->p->drawPath(qpath);
+    qs->p->setPen(Qt::black);
+
+    qs->p->setWorldMatrix (savedMatrix, false);
+
+    if (qs->supports_porter_duff)
+        qs->p->setCompositionMode (QPainter::CompositionMode_SourceOver);
+
+    return CAIRO_INT_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_qpainter_surface_show_glyphs (void *abstract_surface,
+                                     cairo_operator_t op,
+                                     cairo_pattern_t *source,
+                                     cairo_glyph_t *glyphs,
+                                     int num_glyphs,
+                                     cairo_scaled_font_t *scaled_font,
+                                     int *remaining_glyphs)
+{
+    cairo_qpainter_surface_t *qs = (cairo_qpainter_surface_t *) abstract_surface;
+
+#if defined(Q_WS_X11) && defined(CAIRO_HAS_XLIB_XRENDER_SURFACE)
+    /* If we have an equivalent X surface, let the xlib surface handle this
+     * until we figure out how to do this natively with Qt.
+     */
+    if (qs->xlib_equiv) {
+
+	D(fprintf(stderr, "q[%p] show_glyphs (x11 equiv) op:%s nglyphs: %d\n", abstract_surface, _opstr(op), num_glyphs));
+
+	for (int i = 0; i < num_glyphs; i++) {
+	    glyphs[i].x -= qs->redir_offset.x();
+	    glyphs[i].y -= qs->redir_offset.y();
+	}
+
+	if (qs->has_clipping != qs->xlib_has_clipping ||
+	    qs->clip_bounds != qs->xlib_clip_bounds)
+	{
+	    _cairo_surface_reset_clip (qs->xlib_equiv);
+
+	    if (qs->has_clipping) {
+		cairo_region_t region;
+		cairo_rectangle_int_t rect = {
+		    qs->clip_bounds.x() - qs->redir_offset.x(),
+		    qs->clip_bounds.y() - qs->redir_offset.y(),
+		    qs->clip_bounds.width(),
+		    qs->clip_bounds.height()
+		};
+
+		_cairo_region_init_rect (&region, &rect);
+
+		_cairo_surface_set_clip_region (qs->xlib_equiv, &region, ++qs->xlib_clip_serial);
+
+		_cairo_region_fini (&region);
+	    }
+
+	    qs->xlib_has_clipping = qs->has_clipping;
+	    qs->xlib_clip_bounds = qs->clip_bounds;
+	}
+
+        return (cairo_int_status_t)
+               _cairo_surface_show_text_glyphs (qs->xlib_equiv, op, source, NULL, 0, glyphs, num_glyphs, NULL, 0, FALSE, scaled_font);
+    }
+#endif
+
+    return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+static cairo_int_status_t
+_cairo_qpainter_surface_mask (void *abstract_surface,
+                              cairo_operator_t op,
+                              cairo_pattern_t *source,
+                              cairo_pattern_t *mask)
+{
+    cairo_qpainter_surface_t *qs = (cairo_qpainter_surface_t *) abstract_surface;
+
+    D(fprintf(stderr, "q[%p] mask op:%s\n", abstract_surface, _opstr(op)));
+
+    if (!qs->p)
+        return CAIRO_INT_STATUS_SUCCESS;
+
+    if (mask->type == CAIRO_PATTERN_TYPE_SOLID) {
+        cairo_solid_pattern_t *solid_mask = (cairo_solid_pattern_t *) mask;
+        cairo_int_status_t result;
+
+        qs->p->setOpacity (solid_mask->color.alpha);
+
+        result = _cairo_qpainter_surface_paint (abstract_surface, op, source);
+
+        qs->p->setOpacity (1.0);
+
+        return result;
+    }
+
+    // otherwise skip for now
+    return CAIRO_INT_STATUS_SUCCESS;
+}
+
+/**
+ ** XXX this will go away!  it's only implemented for now so that we
+ ** can get some text without show_glyphs being available.
+ **/
+static cairo_int_status_t
+_cairo_qpainter_surface_composite (cairo_operator_t op,
+                                   cairo_pattern_t *pattern,
+                                   cairo_pattern_t *mask_pattern,
+                                   void *abstract_surface,
+                                   int src_x,
+                                   int src_y,
+                                   int mask_x,
+                                   int mask_y,
+                                   int dst_x,
+                                   int dst_y,
+                                   unsigned int width,
+                                   unsigned int height)
+{
+    cairo_qpainter_surface_t *qs = (cairo_qpainter_surface_t *) abstract_surface;
+
+    if (mask_pattern)
+        return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    D(fprintf(stderr, "q[%p] composite op:%s src:%p [%d %d] dst [%d %d] dim [%d %d]\n",
+              abstract_surface, _opstr(op), (void*)pattern,
+              src_x, src_y, dst_x, dst_y, width, height));
+
+    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
+        cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) pattern;
+
+        QColor color;
+        color.setRgbF(solid->color.red,
+                      solid->color.green,
+                      solid->color.blue,
+                      solid->color.alpha);
+
+        if (qs->supports_porter_duff)
+            qs->p->setCompositionMode (_qpainter_compositionmode_from_cairo_op (op));
+
+        qs->p->fillRect (dst_x, dst_y, width, height, color);
+
+        if (qs->supports_porter_duff)
+            qs->p->setCompositionMode (QPainter::CompositionMode_SourceOver);
+    } else if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
+        cairo_surface_pattern_t *spattern = (cairo_surface_pattern_t*) pattern;
+        cairo_surface_t *surface = spattern->surface;
+
+        QImage *qimg = NULL;
+        QPixmap *qpixmap = NULL;
+	std::auto_ptr<QImage> qimg_d;
+
+        if (surface->type == CAIRO_SURFACE_TYPE_IMAGE) {
+            cairo_image_surface_t *isurf = (cairo_image_surface_t*) surface;
+	    qimg = new QImage ((const uchar *) isurf->data,
+			       isurf->width,
+			       isurf->height,
+			       isurf->stride,
+			       _qimage_format_from_cairo_format (isurf->format));
+	    qimg_d.reset(qimg);
+        }
+
+        if (surface->type == CAIRO_SURFACE_TYPE_QPAINTER) {
+            cairo_qpainter_surface_t *qsrc = (cairo_qpainter_surface_t*) surface;
+
+            if (qsrc->image)
+                qimg = qsrc->image;
+            else if (qsrc->pixmap)
+                qpixmap = qsrc->pixmap;
+        }
+
+        if (!qimg && !qpixmap)
+            return CAIRO_INT_STATUS_UNSUPPORTED;
+
+        QMatrix savedMatrix = qs->p->worldMatrix();
+        if (!_cairo_matrix_is_identity (&pattern->matrix)) {
+            cairo_matrix_t pm = pattern->matrix;
+            if (cairo_matrix_invert (&pm) == CAIRO_STATUS_SUCCESS)
+                qs->p->setWorldMatrix(_qmatrix_from_cairo_matrix (pm), true);
+        }
+
+        if (qs->supports_porter_duff)
+            qs->p->setCompositionMode (_qpainter_compositionmode_from_cairo_op (op));
+
+        if (qimg)
+            qs->p->drawImage (dst_x, dst_y, *qimg, src_x, src_y, width, height);
+        else if (qpixmap)
+            qs->p->drawPixmap (dst_x, dst_y, *qpixmap, src_x, src_y, width, height);
+
+        if (qs->supports_porter_duff)
+            qs->p->setCompositionMode (QPainter::CompositionMode_SourceOver);
+    } else {
+        return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    return CAIRO_INT_STATUS_SUCCESS;
+}
+
+/**
+ ** Backend struct
+ **/
+
+static const struct _cairo_surface_backend cairo_qpainter_surface_backend = {
+    CAIRO_SURFACE_TYPE_QPAINTER,
+    _cairo_qpainter_surface_create_similar,
+    _cairo_qpainter_surface_finish,
+    _cairo_qpainter_surface_acquire_source_image,
+    _cairo_qpainter_surface_release_source_image,
+    _cairo_qpainter_surface_acquire_dest_image,
+    _cairo_qpainter_surface_release_dest_image,
+    _cairo_qpainter_surface_clone_similar,
+
+    _cairo_qpainter_surface_composite, /* composite -- XXX temporary! */
+    NULL, /* fill_rectangles */
+    NULL, /* composite_trapezoids */
+    NULL, /* copy_page */
+    NULL, /* show_page */
+    NULL, /* set_clip_region */
+    _cairo_qpainter_surface_intersect_clip_path,
+    _cairo_qpainter_surface_get_extents,
+    NULL, /* old_show_glyphs */
+    NULL, /* get_font_options */
+    NULL, /* flush */
+    NULL, /* mark_dirty_rectangle */
+    NULL, /* scaled_font_fini */
+    NULL, /* scaled_glyph_fini */
+
+    _cairo_qpainter_surface_paint,
+    _cairo_qpainter_surface_mask,
+    _cairo_qpainter_surface_stroke,
+    _cairo_qpainter_surface_fill,
+    _cairo_qpainter_surface_show_glyphs,
+
+    NULL, /* snapshot */
+    NULL, /* is_similar */
+    NULL, /* reset */
+    NULL  /* fill_stroke */
+};
+
+#if defined(Q_WS_X11) && defined(CAIRO_HAS_XLIB_XRENDER_SURFACE)
+void
+_cairo_qpainter_create_xlib_surface (cairo_qpainter_surface_t *qs)
+{
+    Drawable d = None;
+    QX11Info xinfo;
+    int width, height;
+
+    if (!qs->p)
+	return;
+
+    QPaintDevice *pd = qs->p->device();
+    if (!pd)
+	return;
+
+    QPoint offs;
+    QPaintDevice *rpd = QPainter::redirected(pd, &offs);
+    if (rpd) {
+	pd = rpd;
+	qs->redir_offset = offs;
+    }
+
+    if (pd->devType() == QInternal::Widget) {
+	QWidget *w = (QWidget*) pd;
+	d = (Drawable) w->handle();
+	xinfo = w->x11Info();
+	width = w->width();
+	height = w->height();
+    } else if (pd->devType() == QInternal::Pixmap) {
+	QPixmap *pixmap = (QPixmap*) pd;
+	d = (Drawable) pixmap->handle();
+	xinfo = pixmap->x11Info();
+	width = pixmap->width();
+	height = pixmap->height();
+    } else {
+	return;
+    }
+
+    if (d != None) {
+	qs->xlib_equiv = cairo_xlib_surface_create_with_xrender_format
+	    (xinfo.display(),
+	     d,
+	     ScreenOfDisplay(xinfo.display(), xinfo.screen()),
+	     XRenderFindVisualFormat (xinfo.display(), (Visual*) xinfo.visual()),
+	     width,
+	     height);
+    }
+}
+#endif
+
+cairo_surface_t *
+cairo_qpainter_surface_create (QPainter *painter)
+{
+    cairo_qpainter_surface_t *qs;
+
+    qs = (cairo_qpainter_surface_t *) malloc (sizeof(cairo_qpainter_surface_t));
+    if (qs == NULL)
+        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    memset (qs, 0, sizeof(cairo_qpainter_surface_t));
+
+    _cairo_surface_init (&qs->base, &cairo_qpainter_surface_backend, CAIRO_CONTENT_COLOR_ALPHA);
+
+    qs->p = painter;
+    if (qs->p->paintEngine())
+	qs->supports_porter_duff = qs->p->paintEngine()->hasFeature(QPaintEngine::PorterDuff);
+    else
+	qs->supports_porter_duff = FALSE;
+
+    // Save so that we can always get back to the original state
+    qs->p->save();
+
+    qs->window = painter->window();
+
+#if defined(Q_WS_X11) && defined(CAIRO_HAS_XLIB_XRENDER_SURFACE)
+    _cairo_qpainter_create_xlib_surface (qs);
+#endif
+
+    D(fprintf(stderr, "qpainter_surface_create: window: [%d %d %d %d] pd:%d\n",
+              qs->window.x(), qs->window.y(), qs->window.width(), qs->window.height(),
+              qs->supports_porter_duff));
+
+    return &qs->base;
+}
+
+cairo_surface_t *
+cairo_qpainter_surface_create_with_qimage (cairo_format_t format,
+                                           int width,
+                                           int height)
+{
+    cairo_qpainter_surface_t *qs;
+
+    qs = (cairo_qpainter_surface_t *) malloc (sizeof(cairo_qpainter_surface_t));
+    if (qs == NULL)
+        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    memset (qs, 0, sizeof(cairo_qpainter_surface_t));
+
+    _cairo_surface_init (&qs->base, &cairo_qpainter_surface_backend, _cairo_content_from_format (format));
+
+    QImage *image = new QImage (width, height, _qimage_format_from_cairo_format (format));
+
+    qs->image = image;
+
+    if (!image->isNull()) {
+        qs->p = new QPainter(image);
+        qs->supports_porter_duff = qs->p->paintEngine()->hasFeature(QPaintEngine::PorterDuff);
+    }
+
+    qs->image_equiv = (cairo_image_surface_t*)
+                      cairo_image_surface_create_for_data (image->bits(),
+                                                           format,
+                                                           width, height,
+                                                           image->bytesPerLine());
+
+    qs->window = QRect(0, 0, width, height);
+
+    D(fprintf(stderr, "qpainter_surface_create: qimage: [%d %d %d %d] pd:%d\n",
+              qs->window.x(), qs->window.y(), qs->window.width(), qs->window.height(),
+              qs->supports_porter_duff));
+
+    return &qs->base;
+}
+
+cairo_surface_t *
+cairo_qpainter_surface_create_with_qpixmap (cairo_content_t content,
+					    int width,
+                                            int height)
+{
+    cairo_qpainter_surface_t *qs;
+
+    if (content != CAIRO_CONTENT_COLOR &&
+	content != CAIRO_CONTENT_COLOR_ALPHA)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    qs = (cairo_qpainter_surface_t *) malloc (sizeof(cairo_qpainter_surface_t));
+    if (qs == NULL)
+        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    memset (qs, 0, sizeof(cairo_qpainter_surface_t));
+
+    QPixmap *pixmap = new QPixmap (width, height);
+
+    // By default, a QPixmap is opaque; however, if it's filled
+    // with a color with a transparency component, it is converted
+    // to a format that preserves transparency.
+    if (content == CAIRO_CONTENT_COLOR_ALPHA)
+	pixmap->fill(Qt::transparent);
+
+    _cairo_surface_init (&qs->base, &cairo_qpainter_surface_backend,
+			 content);
+
+    qs->pixmap = pixmap;
+
+    if (!pixmap->isNull()) {
+        qs->p = new QPainter(pixmap);
+        qs->supports_porter_duff = qs->p->paintEngine()->hasFeature(QPaintEngine::PorterDuff);
+    }
+
+    qs->window = QRect(0, 0, width, height);
+
+#if defined(Q_WS_X11) && defined(CAIRO_HAS_XLIB_XRENDER_SURFACE)
+    _cairo_qpainter_create_xlib_surface (qs);
+#endif
+
+    D(fprintf(stderr, "qpainter_surface_create: qpixmap: [%d %d %d %d] pd:%d\n",
+              qs->window.x(), qs->window.y(), qs->window.width(), qs->window.height(),
+              qs->supports_porter_duff));
+
+    return &qs->base;
+}
+
+QPainter *
+cairo_qpainter_surface_get_qpainter (cairo_surface_t *surface)
+{
+    cairo_qpainter_surface_t *qs = (cairo_qpainter_surface_t*) surface;
+
+    if (surface->type != CAIRO_SURFACE_TYPE_QPAINTER)
+        return NULL;
+
+    return qs->p;
+}
+
+QImage *
+cairo_qpainter_surface_get_qimage (cairo_surface_t *surface)
+{
+    cairo_qpainter_surface_t *qs = (cairo_qpainter_surface_t*) surface;
+
+    if (surface->type != CAIRO_SURFACE_TYPE_QPAINTER)
+        return NULL;
+
+    return qs->image;
+}
+
+cairo_surface_t *
+cairo_qpainter_surface_get_image (cairo_surface_t *surface)
+{
+    cairo_qpainter_surface_t *qs = (cairo_qpainter_surface_t*) surface;
+
+    if (surface->type != CAIRO_SURFACE_TYPE_QPAINTER)
+        return NULL;
+
+    return (cairo_surface_t*) qs->image_equiv;
+}
+
+/*
+ * TODO:
+ *
+ * - Figure out why QBrush isn't working with non-repeated images
+ *
+ * - Correct repeat mode; right now, every surface source is EXTEND_REPEAT
+ *   - implement EXTEND_NONE (?? probably need to clip to the extents of the source)
+ *   - implement EXTEND_REFLECT (create temporary and copy 4x, then EXTEND_REPEAT that)
+ *
+ * - stroke-image failure
+ *
+ * - Implement mask() with non-solid masks (probably will need to use a temporary and use IN)
+ *
+ * - Implement gradient sources
+ *
+ * - Make create_similar smarter -- create QPixmaps in more circumstances
+ *   (e.g. if the pixmap can have alpha)
+ *
+ * - Implement show_glyphs() in terms of Qt
+ *
+ */
+
+void
+_cairo_image_surface_write_to_ppm (cairo_image_surface_t *isurf, const char *fn)
+{
+    char *fmt;
+    if (isurf->format == CAIRO_FORMAT_ARGB32 || isurf->format == CAIRO_FORMAT_RGB24)
+        fmt = "P6";
+    else if (isurf->format == CAIRO_FORMAT_A8)
+        fmt = "P5";
+    else
+        return;
+
+    FILE *fp = fopen(fn, "wb");
+    if (!fp)
+        return;
+
+    fprintf (fp, "%s %d %d 255\n", fmt,isurf->width, isurf->height);
+    for (int j = 0; j < isurf->height; j++) {
+        unsigned char *row = isurf->data + isurf->stride * j;
+        for (int i = 0; i < isurf->width; i++) {
+            if (isurf->format == CAIRO_FORMAT_ARGB32 || isurf->format == CAIRO_FORMAT_RGB24) {
+                unsigned char r = *row++;
+                unsigned char g = *row++;
+                unsigned char b = *row++;
+                *row++;
+                putc(r, fp);
+                putc(g, fp);
+                putc(b, fp);
+            } else {
+                unsigned char a = *row++;
+                putc(a, fp);
+            }
+        }
+    }
+
+    fclose (fp);
+
+    fprintf (stderr, "Wrote %s\n", fn);
+}
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-qpainter.h
@@ -0,0 +1,79 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2008 Mozilla Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation.
+ *
+ * Contributor(s):
+ *      Vladimir Vukicevic <vladimir@mozilla.com>
+ */
+
+#ifndef CAIRO_QPAINTER_H
+#define CAIRO_QPAINTER_H
+
+#include <cairo.h>
+
+#if CAIRO_HAS_QPAINTER_SURFACE
+
+class QPainter;
+class QImage;
+
+CAIRO_BEGIN_DECLS
+
+cairo_public cairo_surface_t *
+cairo_qpainter_surface_create (QPainter *painter);
+
+cairo_public cairo_surface_t *
+cairo_qpainter_surface_create_with_qimage (cairo_format_t format,
+                                           int width,
+                                           int height);
+
+cairo_public cairo_surface_t *
+cairo_qpainter_surface_create_with_qpixmap (cairo_content_t content,
+					    int width,
+                                            int height);
+
+cairo_public QPainter *
+cairo_qpainter_surface_get_qpainter (cairo_surface_t *surface);
+
+cairo_public cairo_surface_t *
+cairo_qpainter_surface_get_image (cairo_surface_t *surface);
+
+cairo_public QImage *
+cairo_qpainter_surface_get_qimage (cairo_surface_t *surface);
+
+CAIRO_END_DECLS
+
+#else /* CAIRO_HAS_QPAINTER_SURFACE */
+
+# error Cairo was not compiled with support for the QPainter backend
+
+#endif /* CAIRO_HAS_QPAINTER_SURFACE */
+
+#endif /* CAIRO_QPAINTER_H_ */
--- a/gfx/cairo/cairo/src/cairo.h
+++ b/gfx/cairo/cairo/src/cairo.h
@@ -1758,17 +1758,18 @@ typedef enum _cairo_surface_type {
     CAIRO_SURFACE_TYPE_GLITZ,
     CAIRO_SURFACE_TYPE_QUARTZ,
     CAIRO_SURFACE_TYPE_WIN32,
     CAIRO_SURFACE_TYPE_BEOS,
     CAIRO_SURFACE_TYPE_DIRECTFB,
     CAIRO_SURFACE_TYPE_SVG,
     CAIRO_SURFACE_TYPE_OS2,
     CAIRO_SURFACE_TYPE_WIN32_PRINTING,
-    CAIRO_SURFACE_TYPE_QUARTZ_IMAGE
+    CAIRO_SURFACE_TYPE_QUARTZ_IMAGE,
+    CAIRO_SURFACE_TYPE_QPAINTER
 } cairo_surface_type_t;
 
 cairo_public cairo_surface_type_t
 cairo_surface_get_type (cairo_surface_t *surface);
 
 cairo_public cairo_content_t
 cairo_surface_get_content (cairo_surface_t *surface);
 
--- a/gfx/cairo/cairo/src/cairoint.h
+++ b/gfx/cairo/cairo/src/cairoint.h
@@ -368,17 +368,17 @@ typedef struct _cairo_toy_font_face {
     cairo_font_slant_t slant;
     cairo_font_weight_t weight;
 } cairo_toy_font_face_t;
 
 typedef enum _cairo_scaled_glyph_info {
     CAIRO_SCALED_GLYPH_INFO_METRICS	 = (1 << 0),
     CAIRO_SCALED_GLYPH_INFO_SURFACE	 = (1 << 1),
     CAIRO_SCALED_GLYPH_INFO_PATH	 = (1 << 2),
-    CAIRO_SCALED_GLYPH_INFO_META_SURFACE = (1 << 3),
+    CAIRO_SCALED_GLYPH_INFO_META_SURFACE = (1 << 3)
 } cairo_scaled_glyph_info_t;
 
 typedef struct _cairo_scaled_font_subset {
     cairo_scaled_font_t *scaled_font;
     unsigned int font_id;
     unsigned int subset_id;
 
     /* Index of glyphs array is subset_glyph_index.
--- a/gfx/src/thebes/Makefile.in
+++ b/gfx/src/thebes/Makefile.in
@@ -72,16 +72,20 @@ CPPSRCS		= \
 		nsThebesRenderingContext.cpp \
 		nsThebesFontMetrics.cpp \
 		nsThebesFontEnumerator.cpp \
 		$(NULL)
 
 
 EXTRA_DSO_LIBS	= gkgfx thebes
 
+ifeq ($(MOZ_WIDGET_TOOLKIT),qt)
+CPPSRCS += nsSystemFontsQt.cpp
+endif
+
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 CPPSRCS		+= nsSystemFontsGTK2.cpp
 
 ifdef MOZ_ENABLE_GLITZ
 REQUIRES        += glitzglx
 endif
 
 endif
new file mode 100644
--- /dev/null
+++ b/gfx/src/thebes/nsSystemFontsQt.cpp
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is thebes gfx
+ *
+ * The Initial Developer of the Original Code is mozilla.org.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir@pobox.com>
+ *   Stuart Parmenter <pavlov@pavlov.net>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIDeviceContext.h"
+#include "nsIRenderingContext.h"
+
+#include "nsSystemFontsQt.h"
+#include "gfxQtPlatform.h"
+#include <QApplication>
+#include <QFont>
+
+nsSystemFontsQt::nsSystemFontsQt()
+  : mDefaultFontName(NS_LITERAL_STRING("sans-serif"))
+  , mButtonFontName(NS_LITERAL_STRING("sans-serif"))
+  , mFieldFontName(NS_LITERAL_STRING("sans-serif"))
+  , mMenuFontName(NS_LITERAL_STRING("sans-serif"))
+{
+   // What about using QFontInfo? is it faster or what?
+   GetSystemFontInfo("Qlabel", &mDefaultFontName, &mDefaultFontStyle);
+
+   GetSystemFontInfo("QlineEdit", &mFieldFontName, &mFieldFontStyle);
+
+   GetSystemFontInfo("QAction", &mMenuFontName, &mMenuFontStyle);
+  
+   GetSystemFontInfo("QPushButton", &mButtonFontName, &mButtonFontStyle);
+}
+
+nsSystemFontsQt::~nsSystemFontsQt()
+{
+    // No implementation needed
+}
+
+nsresult
+nsSystemFontsQt::GetSystemFontInfo(const char *aClassName, nsString *aFontName,
+                                   gfxFontStyle *aFontStyle) const
+{
+    QFont qFont = QApplication::font(aClassName);
+
+    aFontStyle->style = FONT_STYLE_NORMAL;
+    aFontStyle->systemFont = PR_TRUE;
+    NS_NAMED_LITERAL_STRING(quote, "\"");
+    nsString family((PRUnichar*)qFont.family().data());
+    *aFontName = quote + family + quote;
+    aFontStyle->weight = qFont.weight();
+    aFontStyle->size = qFont.pointSizeF() * float(gfxQtPlatform::DPI()) / 72.0f;
+    return NS_OK;
+}
+
+
+nsresult
+nsSystemFontsQt::GetSystemFont(nsSystemFontID anID, nsString *aFontName,
+                                 gfxFontStyle *aFontStyle) const
+{
+    switch (anID) {
+    case eSystemFont_Menu:         // css2
+    case eSystemFont_PullDownMenu: // css3
+        *aFontName = mMenuFontName;
+        *aFontStyle = mMenuFontStyle;
+        break;
+
+    case eSystemFont_Field:        // css3
+    case eSystemFont_List:         // css3
+        *aFontName = mFieldFontName;
+        *aFontStyle = mFieldFontStyle;
+        break;
+
+    case eSystemFont_Button:       // css3
+        *aFontName = mButtonFontName;
+        *aFontStyle = mButtonFontStyle;
+        break;
+
+    case eSystemFont_Caption:      // css2
+    case eSystemFont_Icon:         // css2
+    case eSystemFont_MessageBox:   // css2
+    case eSystemFont_SmallCaption: // css2
+    case eSystemFont_StatusBar:    // css2
+    case eSystemFont_Window:       // css3
+    case eSystemFont_Document:     // css3
+    case eSystemFont_Workspace:    // css3
+    case eSystemFont_Desktop:      // css3
+    case eSystemFont_Info:         // css3
+    case eSystemFont_Dialog:       // css3
+    case eSystemFont_Tooltips:     // moz
+    case eSystemFont_Widget:       // moz
+        *aFontName = mDefaultFontName;
+        *aFontStyle = mDefaultFontStyle;
+        break;
+    }
+
+    return NS_OK;
+}
+
new file mode 100644
--- /dev/null
+++ b/gfx/src/thebes/nsSystemFontsQt.h
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is thebes gfx
+ *
+ * The Initial Developer of the Original Code is mozilla.org.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir@pobox.com>
+ *   Stuart Parmenter <pavlov@pavlov.net>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _NS_SYSTEMFONTSQT_H_
+#define _NS_SYSTEMFONTSQT_H_
+
+#include <gfxFont.h>
+
+class QFont;
+
+class nsSystemFontsQt
+{
+public:
+    nsSystemFontsQt();
+    ~nsSystemFontsQt();
+
+    nsresult GetSystemFont(nsSystemFontID anID, nsString *aFontName,
+                           gfxFontStyle *aFontStyle) const;
+
+private:
+
+    nsresult GetSystemFontInfo(const char *aClassName, nsString *aFontName,
+                               gfxFontStyle *aFontStyle) const;
+
+    /*
+     * The following system font constants exist:
+     *
+     * css2: http://www.w3.org/TR/REC-CSS2/fonts.html#x27
+     * eSystemFont_Caption, eSystemFont_Icon, eSystemFont_Menu,
+     * eSystemFont_MessageBox, eSystemFont_SmallCaption,
+     * eSystemFont_StatusBar,
+     * // css3
+     * eSystemFont_Window, eSystemFont_Document,
+     * eSystemFont_Workspace, eSystemFont_Desktop,
+     * eSystemFont_Info, eSystemFont_Dialog,
+     * eSystemFont_Button, eSystemFont_PullDownMenu,
+     * eSystemFont_List, eSystemFont_Field,
+     * // moz
+     * eSystemFont_Tooltips, eSystemFont_Widget
+     */
+    nsString mDefaultFontName, mButtonFontName, mFieldFontName, mMenuFontName;
+    gfxFontStyle mDefaultFontStyle, mButtonFontStyle, mFieldFontStyle, mMenuFontStyle;
+};
+
+#endif /* _NS_SYSTEMFONTSQT_H_ */
+
--- a/gfx/src/thebes/nsThebesDeviceContext.cpp
+++ b/gfx/src/thebes/nsThebesDeviceContext.cpp
@@ -86,16 +86,19 @@ static nsSystemFontsOS2 *gSystemFonts = 
 #elif defined(XP_BEOS)
 #include "nsSystemFontsBeOS.h"
 static nsSystemFontsBeOS *gSystemFonts = nsnull;
 #elif XP_MACOSX
 #include "nsSystemFontsMac.h"
 #include "gfxQuartzSurface.h"
 #include "gfxImageSurface.h"
 static nsSystemFontsMac *gSystemFonts = nsnull;
+#elif defined(MOZ_WIDGET_QT)
+#include "nsSystemFontsQt.h"
+static nsSystemFontsQt *gSystemFonts = nsnull;
 #else
 #error Need to declare gSystemFonts!
 #endif
 
 #if defined(MOZ_ENABLE_GTK2) && defined(MOZ_X11)
 extern "C" {
 static int x11_error_handler (Display *dpy, XErrorEvent *err) {
     NS_ASSERTION(PR_FALSE, "X Error");
@@ -223,16 +226,19 @@ nsThebesDeviceContext::SetDPI()
         }
         if (dpi < 0) // something didn't work before, fall back to hardcoded DPI value
             dpi = 96;
 #elif defined(XP_MACOSX)
 
         // we probably want to actually get a real DPI here?
         dpi = 96;
 
+#elif defined(MOZ_WIDGET_QT)
+		// TODO: get real DPI here with Qt methods
+        dpi = 96;
 #else
 #error undefined platform dpi
 #endif
 
         if (prefDPI > 0 && !mPrintingSurface)
             dpi = prefDPI;
     }
 
@@ -391,16 +397,18 @@ nsThebesDeviceContext::GetSystemFont(nsS
 #elif XP_WIN
         gSystemFonts = new nsSystemFontsWin();
 #elif XP_OS2
         gSystemFonts = new nsSystemFontsOS2();
 #elif defined(XP_BEOS)
         gSystemFonts = new nsSystemFontsBeOS();
 #elif XP_MACOSX
         gSystemFonts = new nsSystemFontsMac();
+#elif defined(MOZ_WIDGET_QT)
+        gSystemFonts = new nsSystemFontsQt();
 #else
 #error Need to know how to create gSystemFonts, fix me!
 #endif
     }
 
     nsString fontName;
     gfxFontStyle fontStyle;
     nsresult rv = gSystemFonts->GetSystemFont(aID, &fontName, &fontStyle);
--- a/gfx/thebes/public/Makefile.in
+++ b/gfx/thebes/public/Makefile.in
@@ -71,16 +71,22 @@ endif
 EXPORTS +=  gfxPlatformGtk.h gfxGdkNativeRenderer.h
 EXPORTS +=	gfxPDFSurface.h gfxPSSurface.h
 
 ifdef MOZ_ENABLE_GLITZ
 REQUIRES += glitzglx
 endif
 endif
 
+ifeq ($(MOZ_WIDGET_TOOLKIT),qt)
+EXPORTS += gfxQtPlatform.h gfxQPainterSurface.h
+EXPORTS += gfxXlibSurface.h gfxQtNativeRenderer.h
+EXPORTS += gfxQtFonts.h
+endif
+
 ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
 EXPORTS	+=	gfxOS2Surface.h \
 		gfxOS2Platform.h \
 		gfxOS2Fonts.h \
 		$(NULL)
 EXPORTS +=	gfxPDFSurface.h
 endif
 
--- a/gfx/thebes/public/gfxASurface.h
+++ b/gfx/thebes/public/gfxASurface.h
@@ -77,17 +77,18 @@ public:
         SurfaceTypeGlitz,
         SurfaceTypeQuartz,
         SurfaceTypeWin32,
         SurfaceTypeBeOS,
         SurfaceTypeDirectFB,
         SurfaceTypeSVG,
         SurfaceTypeOS2,
         SurfaceTypeWin32Printing,
-        SurfaceTypeQuartzImage
+        SurfaceTypeQuartzImage,
+        SurfaceTypeQPainter
     } gfxSurfaceType;
 
     typedef enum {
         CONTENT_COLOR       = 0x1000,
         CONTENT_ALPHA       = 0x2000,
         CONTENT_COLOR_ALPHA = 0x3000
     } gfxContentType;
 
@@ -134,16 +135,18 @@ public:
     static PRBool CheckSurfaceSize(const gfxIntSize& sz, PRInt32 limit = 0);
 
     /* Return the default set of context flags for this surface; these are
      * hints to the context about any special rendering considerations.  See
      * gfxContext::SetFlag for documentation.
      */
     virtual PRInt32 GetDefaultContextFlags() const { return 0; }
 
+    static gfxContentType ContentFromFormat(gfxImageFormat format);
+
 protected:
     gfxASurface() : mSurface(nsnull), mFloatingRefs(0), mSurfaceValid(PR_FALSE) { }
 
     static gfxASurface* GetSurfaceWrapper(cairo_surface_t *csurf);
     static void SetSurfaceWrapper(cairo_surface_t *csurf, gfxASurface *asurf);
 
     void Init(cairo_surface_t *surface, PRBool existingSurface = PR_FALSE);
 
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/public/gfxQPainterSurface.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir@pobox.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef GFX_QPAINTERSURFACE_H
+#define GFX_QPAINTERSURFACE_H
+
+#include "gfxASurface.h"
+#include "gfxImageSurface.h"
+
+class QPainter;
+class QImage;
+
+class THEBES_API gfxQPainterSurface : public gfxASurface {
+public:
+    gfxQPainterSurface(QPainter *painter);
+    gfxQPainterSurface(const gfxIntSize& size, gfxImageFormat format);
+    gfxQPainterSurface(const gfxIntSize& size, gfxContentType content);
+
+    gfxQPainterSurface(cairo_surface_t *csurf);
+
+    virtual ~gfxQPainterSurface();
+
+    QPainter *GetQPainter() { return mPainter; }
+
+    QImage *GetQImage();
+    already_AddRefed<gfxImageSurface> GetImageSurface();
+
+protected:
+    QPainter *mPainter;
+};
+
+#endif /* GFX_QPAINTERSURFACE_H */
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/public/gfxQtFonts.h
@@ -0,0 +1,178 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Foundation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir@mozilla.com>
+ *   Masayuki Nakano <masayuki@d-toybox.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef GFX_QTFONTS_H
+#define GFX_QTFONTS_H
+
+#include "cairo.h"
+#include "gfxTypes.h"
+#include "gfxFont.h"
+#include "gfxContext.h"
+#include "gfxFontUtils.h"
+
+typedef struct FT_FaceRec_* FT_Face;
+
+/**
+ * FontFamily is a class that describes one of the fonts on the users system.  It holds
+ * each FontEntry (maps more directly to a font face) which holds font type, charset info
+ * and character map info.
+ */
+class FontEntry;
+class FontFamily : public gfxFontFamily
+{
+public:
+    FontFamily(const nsAString& aName) :
+        gfxFontFamily(aName) { }
+
+    FontEntry *FindFontEntry(const gfxFontStyle& aFontStyle);
+
+public:
+    nsTArray<nsRefPtr<FontEntry> > mFaces;
+};
+
+class FontEntry : public gfxFontEntry
+{
+public:
+    FontEntry(const nsAString& aFaceName) :
+        gfxFontEntry(aFaceName)
+    {
+        mFontFace = nsnull;
+        mFTFontIndex = 0;
+        mUnicodeFont = PR_FALSE;
+        mSymbolFont = PR_FALSE;
+    }
+
+    FontEntry(const FontEntry& aFontEntry);
+    ~FontEntry();
+
+    const nsString& GetName() const {
+        return mFaceName;
+    }
+
+    cairo_font_face_t *CairoFontFace();
+
+    cairo_font_face_t *mFontFace;
+
+    nsString mFaceName;
+    nsCString mFilename;
+    PRUint8 mFTFontIndex;
+
+    PRPackedBool mTrueType    : 1;
+    PRPackedBool mIsType1     : 1;
+};
+
+
+
+class gfxQtFont : public gfxFont {
+public: // new functions
+    gfxQtFont(FontEntry *aFontEntry,
+               const gfxFontStyle *aFontStyle);
+    virtual ~gfxQtFont ();
+
+    virtual const gfxFont::Metrics& GetMetrics();
+
+    cairo_font_face_t *CairoFontFace();
+    cairo_scaled_font_t *CairoScaledFont();
+
+    virtual PRBool SetupCairoFont(gfxContext *aContext);
+    virtual nsString GetUniqueName();
+    virtual PRUint32 GetSpaceGlyph();
+
+    FontEntry *GetFontEntry();
+private:
+    cairo_scaled_font_t *mScaledFont;
+
+    PRBool mHasSpaceGlyph;
+    PRUint32 mSpaceGlyph;
+    PRBool mHasMetrics;
+    Metrics mMetrics;
+    gfxFloat mAdjustedSize;
+
+};
+
+class THEBES_API gfxQtFontGroup : public gfxFontGroup {
+public: // new functions
+    gfxQtFontGroup (const nsAString& families,
+                    const gfxFontStyle *aStyle);
+    virtual ~gfxQtFontGroup ();
+
+    inline gfxQtFont *GetFontAt (PRInt32 i) {
+        return static_cast <gfxQtFont *>(static_cast <gfxFont *>(mFonts[i]));
+    }
+
+protected: // from gfxFontGroup
+    virtual gfxTextRun *MakeTextRun(const PRUnichar *aString, 
+                                    PRUint32 aLength,
+                                    const Parameters *aParams, 
+                                    PRUint32 aFlags);
+
+    virtual gfxTextRun *MakeTextRun(const PRUint8 *aString, 
+                                    PRUint32 aLength,
+                                    const Parameters *aParams, 
+                                    PRUint32 aFlags);
+
+    virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
+
+
+protected: // new functions
+    void InitTextRun(gfxTextRun *aTextRun);
+
+    void CreateGlyphRunsFT(gfxTextRun *aTextRun);
+    void AddRange(gfxTextRun *aTextRun, gfxQtFont *font, const PRUnichar *str, PRUint32 len);
+
+    static PRBool FontCallback (const nsAString & fontName, 
+                                const nsACString & genericName, 
+                                void *closure);
+    PRBool mEnableKerning;
+
+    gfxQtFont *FindFontForChar(PRUint32 ch, PRUint32 prevCh, PRUint32 nextCh, gfxQtFont *aFont);
+    PRUint32 ComputeRanges();
+
+    struct TextRange {
+        TextRange(PRUint32 aStart,  PRUint32 aEnd) : start(aStart), end(aEnd) { }
+        PRUint32 Length() const { return end - start; }
+        nsRefPtr<gfxQtFont> font;
+        PRUint32 start, end;
+    };
+
+    nsTArray<TextRange> mRanges;
+    nsString mString;
+};
+
+#endif /* GFX_QTFONTS_H */
+
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/public/gfxQtNativeRenderer.h
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Novell code.
+ *
+ * The Initial Developer of the Original Code is Novell.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   rocallahan@novell.com
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef GFXQTNATIVERENDER_H_
+#define GFXQTNATIVERENDER_H_
+
+#include "gfxColor.h"
+
+class gfxASurface;
+class gfxContext;
+
+class QWidget;
+class QRect;
+
+/**
+ * This class lets us take code that draws into an Qt drawable and lets us
+ * use it to draw into any Thebes context. The user should subclass this class,
+ * override NativeDraw, and then call Draw(). The drawing will be subjected
+ * to all Thebes transformations, clipping etc.
+ */
+class THEBES_API gfxQtNativeRenderer {
+public:
+    /**
+     * Perform the native drawing.
+     * @param offsetX draw at this offset into the given drawable
+     * @param offsetY draw at this offset into the given drawable
+     * @param clipRects an array of rects; clip to the union
+     * @param numClipRects the number of rects in the array, or zero if
+     * no clipping is required
+     */
+    virtual nsresult NativeDraw(QWidget * drawable, short offsetX, 
+            short offsetY, QRect * clipRects, PRUint32 numClipRects) = 0;
+  
+    enum {
+        // If set, then Draw() is opaque, i.e., every pixel in the intersection
+        // of the clipRect and (offset.x,offset.y,bounds.width,bounds.height)
+        // will be set and there is no dependence on what the existing pixels
+        // in the drawable are set to.
+        DRAW_IS_OPAQUE = 0x01,
+        // If set, then offset may be non-zero; if not set, then Draw() can
+        // only be called with offset==(0,0)
+        DRAW_SUPPORTS_OFFSET = 0x02,
+        // If set, then numClipRects can be zero or one
+        DRAW_SUPPORTS_CLIP_RECT = 0x04,
+        // If set, then numClipRects can be any value. If neither this
+        // nor CLIP_RECT are set, then numClipRects will be zero
+        DRAW_SUPPORTS_CLIP_LIST = 0x08,
+        // If set, then the visual passed in can be any visual, otherwise the
+        // visual passed in must be the default visual for dpy's default screen
+        DRAW_SUPPORTS_NONDEFAULT_VISUAL = 0x10,
+        // If set, then the Screen 'screen' in the callback can be different
+        // from the default Screen of the display passed to 'Draw' and can be
+        // on a different display.
+        DRAW_SUPPORTS_ALTERNATE_SCREEN = 0x20
+    };
+
+    struct DrawOutput {
+        nsRefPtr<gfxASurface> mSurface;
+        PRPackedBool mUniformAlpha;
+        PRPackedBool mUniformColor;
+        gfxRGBA      mColor;
+    };
+
+    /**
+     * @param flags see above
+     * @param bounds Draw()'s drawing is guaranteed to be restricted to
+     * the rectangle (offset.x,offset.y,bounds.width,bounds.height)
+     * @param dpy a display to use for the drawing if ctx doesn't have one
+     * @param resultSurface if non-null, we will try to capture a copy of the
+     * rendered image into a surface similar to the surface of ctx; if
+     * successful, a pointer to the new gfxASurface is stored in *resultSurface,
+     * otherwise *resultSurface is set to nsnull.
+     */
+    nsresult Draw(gfxContext* ctx, int width, int height,
+                  PRUint32 flags, DrawOutput* output);
+};
+
+#endif /*GFXQTNATIVERENDER_H_*/
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/public/gfxQtPlatform.h
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Foundation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir@pobox.com>
+ *   Masayuki Nakano <masayuki@d-toybox.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef GFX_PLATFORM_QT_H
+#define GFX_PLATFORM_QT_H
+
+#include "gfxPlatform.h"
+#include "nsDataHashtable.h"
+
+typedef struct FT_LibraryRec_ *FT_Library;
+
+class gfxFontconfigUtils;
+class FontFamily;
+class FontEntry;
+
+class THEBES_API gfxQtPlatform : public gfxPlatform {
+public:
+    gfxQtPlatform();
+    virtual ~gfxQtPlatform();
+
+    static gfxQtPlatform *GetPlatform() {
+        return (gfxQtPlatform*) gfxPlatform::GetPlatform();
+    }
+
+    already_AddRefed<gfxASurface> CreateOffscreenSurface(const gfxIntSize& size,
+                                                         gfxASurface::gfxImageFormat imageFormat);
+
+    nsresult GetFontList(const nsACString& aLangGroup,
+                         const nsACString& aGenericFamily,
+                         nsStringArray& aListOfFonts);
+
+    nsresult UpdateFontList();
+
+    nsresult ResolveFontName(const nsAString& aFontName,
+                             FontResolverCallback aCallback,
+                             void *aClosure, PRBool& aAborted);
+
+    nsresult GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName);
+
+    gfxFontGroup *CreateFontGroup(const nsAString &aFamilies,
+                                  const gfxFontStyle *aStyle);
+
+    FontFamily *FindFontFamily(const nsAString& aName);
+    FontEntry *FindFontEntry(const nsAString& aFamilyName, const gfxFontStyle& aFontStyle);
+
+    static PRInt32 DPI() {
+        if (sDPI == -1) {
+            InitDPI();
+        }
+        NS_ASSERTION(sDPI > 0, "Something is wrong");
+        return sDPI;
+    }
+
+    FT_Library GetFTLibrary();
+
+protected:
+    static void InitDPI();
+
+    static PRInt32 sDPI;
+    static gfxFontconfigUtils *sFontconfigUtils;
+
+private:
+    virtual cmsHPROFILE GetPlatformCMSOutputProfile();
+};
+
+#endif /* GFX_PLATFORM_QT_H */
+
--- a/gfx/thebes/src/Makefile.in
+++ b/gfx/thebes/src/Makefile.in
@@ -106,16 +106,26 @@ endif
 
 EXTRA_DSO_LDOPTS += $(MOZ_PANGO_LIBS) $(ZLIB_LIBS) $(MOZ_XFT_LIBS) $(XLDFLAGS) $(XLIBS)
 endif
 
 ifdef MOZ_DFB
 CPPSRCS += gfxDirectFBSurface.cpp
 endif
 
+ifeq ($(MOZ_WIDGET_TOOLKIT),qt)
+CPPSRCS += gfxQtPlatform.cpp gfxQPainterSurface.cpp
+CPPSRCS += gfxXlibSurface.cpp gfxQtNativeRenderer.cpp
+CPPSRCS += gfxQtFonts.cpp
+CPPSRCS +=	gfxFontconfigUtils.cpp
+CPPSRCS +=	nsUnicodeRange.cpp
+#CSRCS = cairo-xlib-utils.c
+EXTRA_DSO_LDOPTS += $(ZLIB_LIBS) $(MOZ_XFT_LIBS) $(XLDFLAGS) $(XLIBS) $(CAIRO_FT_LIBS)
+endif
+
 ifeq ($(MOZ_WIDGET_TOOLKIT),beos)
 CPPSRCS	+= 	gfxBeOSSurface.cpp gfxBeOSPlatform.cpp
 CPPSRCS +=	gfxPangoFonts.cpp 
 #CPPSRCS +=	gfxPDFSurface.cpp
 CPPSRCS +=	gfxFontconfigUtils.cpp
 CPPSRCS +=	nsUnicodeRange.cpp
 EXTRA_DSO_LDOPTS += $(MOZ_PANGO_LIBS) $(CAIRO_FT_LIBS) -lfontconfig -lpangocairo-1.0
 endif
@@ -177,8 +187,13 @@ endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),beos)
 CXXFLAGS += $(CAIRO_FT_CFLAGS)
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
 CXXFLAGS += $(CAIRO_FT_CFLAGS)
 endif
+
+ifeq ($(MOZ_WIDGET_TOOLKIT),qt)
+CXXFLAGS += $(CAIRO_FT_CFLAGS)
+endif
+
--- a/gfx/thebes/src/gfxASurface.cpp
+++ b/gfx/thebes/src/gfxASurface.cpp
@@ -54,16 +54,20 @@
 #include "gfxQuartzSurface.h"
 #include "gfxQuartzImageSurface.h"
 #endif
 
 #ifdef CAIRO_HAS_DIRECTFB_SURFACE
 #include "gfxDirectFBSurface.h"
 #endif
 
+#ifdef CAIRO_HAS_QPAINTER_SURFACE
+#include "gfxQPainterSurface.h"
+#endif
+
 #include <stdio.h>
 #include <limits.h>
 
 static cairo_user_data_key_t gfxasurface_pointer_key;
 
 // Surfaces use refcounting that's tied to the cairo surface refcnt, to avoid
 // refcount mismatch issues.
 nsrefcnt
@@ -167,16 +171,21 @@ gfxASurface::Wrap (cairo_surface_t *csur
         result = new gfxQuartzImageSurface(csurf);
     }
 #endif
 #ifdef CAIRO_HAS_DIRECTFB_SURFACE
     else if (stype == CAIRO_SURFACE_TYPE_DIRECTFB) {
         result = new gfxDirectFBSurface(csurf);
     }
 #endif
+#ifdef CAIRO_HAS_QPAINTER_SURFACE
+    else if (stype == CAIRO_SURFACE_TYPE_QPAINTER) {
+        result = new gfxQPainterSurface(csurf);
+    }
+#endif
     else {
         result = new gfxUnknownSurface(csurf);
     }
 
     // fprintf(stderr, "New wrapper for %p -> %p\n", csurf, result);
 
     NS_ADDREF(result);
     return result;
@@ -349,8 +358,26 @@ gfxASurface::BeginPage()
     return NS_OK;
 }
 
 nsresult
 gfxASurface::EndPage()
 {
     return NS_OK;
 }
+
+gfxASurface::gfxContentType
+gfxASurface::ContentFromFormat(gfxImageFormat format)
+{
+    switch (format) {
+        case ImageFormatARGB32:
+            return CONTENT_COLOR_ALPHA;
+        case ImageFormatRGB24:
+            return CONTENT_COLOR;
+        case ImageFormatA8:
+        case ImageFormatA1:
+            return CONTENT_ALPHA;
+
+        case ImageFormatUnknown:
+        default:
+            return CONTENT_COLOR;
+    }
+}
--- a/gfx/thebes/src/gfxFont.cpp
+++ b/gfx/thebes/src/gfxFont.cpp
@@ -956,18 +956,20 @@ gfxFontGroup::ForEachFontInternal(const 
                     CopyASCIItoUTF16(lcFamily, genericFamily);
                     family = value;
                 }
             } else {
                 generic = PR_FALSE;
                 genericFamily.SetIsVoid(PR_TRUE);
             }
         }
-        
-        if (!family.IsEmpty()) {
+
+        if (generic) {
+            ForEachFontInternal(family, lang, PR_FALSE, aResolveFontName, fc, closure);
+        } else if (!family.IsEmpty()) {
             NS_LossyConvertUTF16toASCII gf(genericFamily);
             if (aResolveFontName) {
                 ResolveData data(fc, gf, closure);
                 PRBool aborted;
                 gfxPlatform *pf = gfxPlatform::GetPlatform();
                 nsresult rv = pf->ResolveFontName(family,
                                                   gfxFontGroup::FontResolverProc,
                                                   &data, aborted);
old mode 100755
new mode 100644
old mode 100755
new mode 100644
--- a/gfx/thebes/src/gfxPlatform.cpp
+++ b/gfx/thebes/src/gfxPlatform.cpp
@@ -39,16 +39,18 @@
 
 #if defined(XP_WIN)
 #include "gfxWindowsPlatform.h"
 #elif defined(XP_MACOSX)
 #include "gfxPlatformMac.h"
 #include "gfxQuartzFontCache.h"
 #elif defined(MOZ_WIDGET_GTK2)
 #include "gfxPlatformGtk.h"
+#elif defined(MOZ_WIDGET_QT)
+#include "gfxQtPlatform.h"
 #elif defined(XP_BEOS)
 #include "gfxBeOSPlatform.h"
 #elif defined(XP_OS2)
 #include "gfxOS2Platform.h"
 #endif
 
 #include "gfxContext.h"
 #include "gfxImageSurface.h"
@@ -133,16 +135,18 @@ gfxPlatform::Init()
 {
     NS_ASSERTION(!gPlatform, "Already started???");
 #if defined(XP_WIN)
     gPlatform = new gfxWindowsPlatform;
 #elif defined(XP_MACOSX)
     gPlatform = new gfxPlatformMac;
 #elif defined(MOZ_WIDGET_GTK2)
     gPlatform = new gfxPlatformGtk;
+#elif defined(MOZ_WIDGET_QT)
+    gPlatform = new gfxQtPlatform;
 #elif defined(XP_BEOS)
     gPlatform = new gfxBeOSPlatform;
 #elif defined(XP_OS2)
     gPlatform = new gfxOS2Platform;
 #endif
     if (!gPlatform)
         return NS_ERROR_OUT_OF_MEMORY;
 
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/src/gfxQPainterSurface.cpp
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir@pobox.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <assert.h>
+
+#include "gfxQPainterSurface.h"
+#include "gfxImageSurface.h"
+
+#include "cairo-qpainter.h"
+
+gfxQPainterSurface::gfxQPainterSurface(QPainter *painter)
+{
+    cairo_surface_t *csurf = cairo_qpainter_surface_create (painter);
+
+    mPainter = painter;
+
+    Init (csurf);
+}
+
+gfxQPainterSurface::gfxQPainterSurface(const gfxIntSize& size, gfxImageFormat format)
+{
+    cairo_surface_t *csurf = cairo_qpainter_surface_create_with_qimage ((cairo_format_t) format,
+                                                                        size.width,
+                                                                        size.height);
+    mPainter = cairo_qpainter_surface_get_qpainter (csurf);
+
+    Init (csurf);
+}
+
+gfxQPainterSurface::gfxQPainterSurface(const gfxIntSize& size, gfxContentType content)
+{
+    cairo_surface_t *csurf = cairo_qpainter_surface_create_with_qpixmap ((cairo_content_t) content,
+                                                                         size.width,
+                                                                         size.height);
+    mPainter = cairo_qpainter_surface_get_qpainter (csurf);
+
+    Init (csurf);
+}
+
+gfxQPainterSurface::gfxQPainterSurface(cairo_surface_t *csurf)
+{
+    mPainter = cairo_qpainter_surface_get_qpainter (csurf);
+
+    Init(csurf, PR_TRUE);
+}
+
+gfxQPainterSurface::~gfxQPainterSurface()
+{
+}
+
+QImage *
+gfxQPainterSurface::GetQImage()
+{
+    if (!mSurfaceValid)
+        return nsnull;
+
+    return cairo_qpainter_surface_get_qimage(CairoSurface());
+}
+
+already_AddRefed<gfxImageSurface>
+gfxQPainterSurface::GetImageSurface()
+{
+    if (!mSurfaceValid)
+        return nsnull;
+
+    cairo_surface_t *isurf = cairo_qpainter_surface_get_image(CairoSurface());
+    if (!isurf)
+        return nsnull;
+
+    assert(cairo_surface_get_type(isurf) == CAIRO_SURFACE_TYPE_IMAGE);
+
+    nsRefPtr<gfxImageSurface> asurf = new gfxImageSurface(isurf);
+    return asurf.forget();
+}
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/src/gfxQtFonts.cpp
@@ -0,0 +1,955 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Foundation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "gfxQtPlatform.h"
+#include "gfxTypes.h"
+#include "gfxQtFonts.h"
+#include "qrect.h"
+#include <locale.h>
+#include <qfontinfo.h>
+#include "cairo-ft.h"
+#include <freetype/tttables.h>
+#include "gfxFontUtils.h"
+
+/**
+ * FontEntry
+ */
+
+FontEntry::FontEntry(const FontEntry& aFontEntry) :
+    gfxFontEntry(aFontEntry)
+{
+    if (aFontEntry.mFontFace)
+        mFontFace = cairo_font_face_reference(aFontEntry.mFontFace);
+    else
+        mFontFace = nsnull;
+}
+
+FontEntry::~FontEntry()
+{
+    if (mFontFace) {
+        cairo_font_face_destroy(mFontFace);
+        mFontFace = nsnull;
+    }
+}
+
+static void
+FTFontDestroyFunc(void *data)
+{
+    FT_Face face = (FT_Face)data;
+    FT_Done_Face(face);
+}
+
+cairo_font_face_t *
+FontEntry::CairoFontFace()
+{
+    static cairo_user_data_key_t key;
+
+    if (!mFontFace) {
+        FT_Face face;
+        FT_New_Face(gfxQtPlatform::GetPlatform()->GetFTLibrary(), mFilename.get(), mFTFontIndex, &face);
+        mFontFace = cairo_ft_font_face_create_for_ft_face(face, 0);
+        cairo_font_face_set_user_data(mFontFace, &key, face, FTFontDestroyFunc);
+    }
+    return mFontFace;
+}
+
+FontEntry *
+FontFamily::FindFontEntry(const gfxFontStyle& aFontStyle)
+{
+    PRBool italic = (aFontStyle.style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) != 0;
+
+    FontEntry *weightList[10] = { 0 };
+    for (PRUint32 j = 0; j < 2; j++) {
+        PRBool matchesSomething = PR_FALSE;
+        // build up an array of weights that match the italicness we're looking for
+        for (PRUint32 i = 0; i < mFaces.Length(); i++) {
+            FontEntry *fe = mFaces[i];
+            const PRUint8 weight = (fe->mWeight / 100);
+            if (fe->mItalic == italic) {
+                weightList[weight] = fe;
+                matchesSomething = PR_TRUE;
+            }
+        }
+        if (matchesSomething)
+            break;
+        italic = !italic;
+    }
+
+    PRInt8 baseWeight, weightDistance;
+    aFontStyle.ComputeWeightAndOffset(&baseWeight, &weightDistance);
+
+    // 500 isn't quite bold so we want to treat it as 400 if we don't
+    // have a 500 weight
+    if (baseWeight == 5 && weightDistance == 0) {
+        // If we have a 500 weight then use it
+        if (weightList[5])
+            return weightList[5];
+
+        // Otherwise treat as 400
+        baseWeight = 4;
+    }
+
+    PRInt8 matchBaseWeight = 0;
+    PRInt8 direction = (baseWeight > 5) ? 1 : -1;
+    for (PRInt8 i = baseWeight; ; i += direction) {
+        if (weightList[i]) {
+            matchBaseWeight = i;
+            break;
+        }
+
+        // if we've reached one side without finding a font,
+        // go the other direction until we find a match
+        if (i == 1 || i == 9)
+            direction = -direction;
+    }
+
+    FontEntry *matchFE;
+    const PRInt8 absDistance = abs(weightDistance);
+    direction = (weightDistance >= 0) ? 1 : -1;
+    for (PRInt8 i = matchBaseWeight, k = 0; i < 10 && i > 0; i += direction) {
+        if (weightList[i]) {
+            matchFE = weightList[i];
+            k++;
+        }
+        if (k > absDistance)
+            break;
+    }
+
+    if (!matchFE)
+        matchFE = weightList[matchBaseWeight];
+
+    NS_ASSERTION(matchFE, "we should always be able to return something here");
+    return matchFE;
+}
+
+
+
+/**
+ * gfxQtFontGroup
+ */
+
+PRBool
+gfxQtFontGroup::FontCallback(const nsAString& fontName,
+                             const nsACString& genericName,
+                             void *closure)
+{
+    nsStringArray *sa = static_cast<nsStringArray*>(closure);
+
+    if (!fontName.IsEmpty() && sa->IndexOf(fontName) < 0) {
+        sa->AppendString(fontName);
+#ifdef DEBUG_pavlov
+        printf(" - %s\n", NS_ConvertUTF16toUTF8(fontName).get());
+#endif
+    }
+
+    return PR_TRUE;
+}
+
+/**
+ * Look up the font in the gfxFont cache. If we don't find it, create one.
+ * In either case, add a ref, append it to the aFonts array, and return it ---
+ * except for OOM in which case we do nothing and return null.
+ */
+static already_AddRefed<gfxQtFont>
+GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle)
+{
+    nsRefPtr<gfxFont> font = gfxFontCache::GetCache()->Lookup(aName, aStyle);
+    if (!font) {
+        FontEntry *fe = gfxQtPlatform::GetPlatform()->FindFontEntry(aName, *aStyle);
+        if (!fe) {
+            printf("Failed to find font entry for %s\n", NS_ConvertUTF16toUTF8(aName).get());
+            return nsnull;
+        }
+
+        font = new gfxQtFont(fe, aStyle);
+        if (!font)
+            return nsnull;
+        gfxFontCache::GetCache()->AddNew(font);
+    }
+    gfxFont *f = nsnull;
+    font.swap(f);
+    return static_cast<gfxQtFont *>(f);
+}
+
+
+gfxQtFontGroup::gfxQtFontGroup(const nsAString& families,
+                               const gfxFontStyle *aStyle)
+    : gfxFontGroup(families, aStyle)
+{
+#ifdef DEBUG_pavlov
+    printf("Looking for %s\n", NS_ConvertUTF16toUTF8(families).get());
+#endif
+    nsStringArray familyArray;
+    ForEachFont(FontCallback, &familyArray);
+
+    if (familyArray.Count() == 0) {
+        nsAutoString prefFamilies;
+        gfxQtPlatform::GetPlatform()->GetPrefFonts(aStyle->langGroup.get(), prefFamilies, nsnull);
+        if (!prefFamilies.IsEmpty()) {
+            ForEachFont(prefFamilies, aStyle->langGroup, FontCallback, &familyArray);
+        }
+    }
+    if (familyArray.Count() == 0) {
+        printf("failde to find a font. sadface\n");
+        // We want to get rid of this entirely at some point, but first we need real lists of fonts.
+        QFont defaultFont;
+        QFontInfo fi (defaultFont);
+        familyArray.AppendString(nsDependentString(static_cast<const PRUnichar *>(fi.family().utf16())));
+    }
+
+    for (int i = 0; i < familyArray.Count(); i++) {
+        nsRefPtr<gfxQtFont> font = GetOrMakeFont(*familyArray[i], &mStyle);
+        if (font) {
+            mFonts.AppendElement(font);
+        }
+    }
+}
+
+gfxQtFontGroup::~gfxQtFontGroup()
+{
+}
+
+gfxFontGroup *
+gfxQtFontGroup::Copy(const gfxFontStyle *aStyle)
+{
+     return new gfxQtFontGroup(mFamilies, aStyle);
+}
+
+/**
+ * We use this to append an LTR or RTL Override character to the start of the
+ * string. This forces Pango to honour our direction even if there are neutral
+ * characters in the string.
+ */
+static PRInt32 AppendDirectionalIndicatorUTF8(PRBool aIsRTL, nsACString& aString)
+{
+    static const PRUnichar overrides[2][2] = { { 0x202d, 0 }, { 0x202e, 0 }}; // LRO, RLO
+    AppendUTF16toUTF8(overrides[aIsRTL], aString);
+    return 3; // both overrides map to 3 bytes in UTF8
+}
+
+gfxTextRun *gfxQtFontGroup::MakeTextRun(const PRUnichar* aString, PRUint32 aLength,
+                                        const Parameters* aParams, PRUint32 aFlags)
+{
+    gfxTextRun *textRun = gfxTextRun::Create(aParams, aString, aLength, this, aFlags);
+    if (!textRun)
+        return nsnull;
+
+    textRun->RecordSurrogates(aString);
+
+    mString.Assign(nsDependentSubstring(aString, aString + aLength));
+
+    InitTextRun(textRun);
+
+    textRun->FetchGlyphExtents(aParams->mContext);
+
+    return textRun;
+}
+
+gfxTextRun *gfxQtFontGroup::MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
+                                        const Parameters *aParams, PRUint32 aFlags)
+{
+    NS_ASSERTION(aFlags & TEXT_IS_8BIT, "8bit should have been set");
+    gfxTextRun *textRun = gfxTextRun::Create(aParams, aString, aLength, this, aFlags);
+    if (!textRun)
+        return nsnull;
+
+    const char *chars = reinterpret_cast<const char *>(aString);
+
+    mString.Assign(NS_ConvertASCIItoUTF16(nsDependentCSubstring(chars, chars + aLength)));
+
+    InitTextRun(textRun);
+
+    textRun->FetchGlyphExtents(aParams->mContext);
+
+    return textRun;
+}
+
+void gfxQtFontGroup::InitTextRun(gfxTextRun *aTextRun)
+{
+    CreateGlyphRunsFT(aTextRun);
+}
+
+
+// Helper function to return the leading UTF-8 character in a char pointer
+// as 32bit number. Also sets the length of the current character (i.e. the
+// offset to the next one) in the second argument
+PRUint32 getUTF8CharAndNext(const PRUint8 *aString, PRUint8 *aLength)
+{
+    *aLength = 1;
+    if (aString[0] < 0x80) { // normal 7bit ASCII char
+        return aString[0];
+    }
+    if ((aString[0] >> 5) == 6) { // two leading ones -> two bytes
+        *aLength = 2;
+        return ((aString[0] & 0x1F) << 6) + (aString[1] & 0x3F);
+    }
+    if ((aString[0] >> 4) == 14) { // three leading ones -> three bytes
+        *aLength = 3;
+        return ((aString[0] & 0x0F) << 12) + ((aString[1] & 0x3F) << 6) +
+               (aString[2] & 0x3F);
+    }
+    if ((aString[0] >> 4) == 15) { // four leading ones -> four bytes
+        *aLength = 4;
+        return ((aString[0] & 0x07) << 18) + ((aString[1] & 0x3F) << 12) +
+               ((aString[2] & 0x3F) <<  6) + (aString[3] & 0x3F);
+    }
+    return aString[0];
+}
+
+
+
+
+
+
+
+
+PRBool
+HasCharacter(gfxQtFont *aFont, PRUint32 ch)
+{
+    if (aFont->GetFontEntry()->mCharacterMap.test(ch))
+        return PR_TRUE;
+
+    // XXX move this lock way way out
+    FT_Face face = cairo_ft_scaled_font_lock_face(aFont->CairoScaledFont());
+    FT_UInt gid = FT_Get_Char_Index(face, ch);
+    cairo_ft_scaled_font_unlock_face(aFont->CairoScaledFont());
+
+    if (gid != 0) {
+        aFont->GetFontEntry()->mCharacterMap.set(ch);
+        return PR_TRUE;
+    }
+    return PR_FALSE;
+}
+
+#if 0
+inline FontEntry *
+gfxQtFontGroup::WhichFontSupportsChar(const nsTArray<>& foo, PRUint32 ch)
+{
+    for (int i = 0; i < aGroup->FontListLength(); i++) {
+        nsRefPtr<gfxQtFont> font = aGroup->GetFontAt(i);
+        if (HasCharacter(font, ch))
+            return font;
+    }
+    return nsnull;
+}
+#endif
+
+inline gfxQtFont *
+gfxQtFontGroup::FindFontForChar(PRUint32 ch, PRUint32 prevCh, PRUint32 nextCh, gfxQtFont *aFont)
+{
+    gfxQtFont *selectedFont;
+
+    // if this character or the next one is a joiner use the
+    // same font as the previous range if we can
+    if (gfxFontUtils::IsJoiner(ch) || gfxFontUtils::IsJoiner(prevCh) || gfxFontUtils::IsJoiner(nextCh)) {
+        if (aFont && HasCharacter(aFont, ch))
+            return aFont;
+    }
+
+    for (PRUint32 i = 0; i < FontListLength(); i++) {
+        nsRefPtr<gfxQtFont> font = GetFontAt(i);
+        if (HasCharacter(font, ch))
+            return font;
+    }
+    return nsnull;
+
+#if 0
+    // check the list of fonts
+    selectedFont = WhichFontSupportsChar(mGroup->GetFontList(), ch);
+
+
+    // don't look in other fonts if the character is in a Private Use Area
+    if ((ch >= 0xE000  && ch <= 0xF8FF) || 
+        (ch >= 0xF0000 && ch <= 0x10FFFD))
+        return selectedFont;
+
+    // check out the style's language group
+    if (!selectedFont) {
+        nsAutoTArray<nsRefPtr<FontEntry>, 5> fonts;
+        this->GetPrefFonts(mGroup->GetStyle()->langGroup.get(), fonts);
+        selectedFont = WhichFontSupportsChar(fonts, ch);
+    }
+
+    // otherwise search prefs
+    if (!selectedFont) {
+        /* first check with the script properties to see what they think */
+        if (ch <= 0xFFFF) {
+            PRUint32 unicodeRange = FindCharUnicodeRange(ch);
+            
+            /* special case CJK */
+            if (unicodeRange == kRangeSetCJK) {
+                if (PR_LOG_TEST(gFontLog, PR_LOG_DEBUG))
+                    PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Trying to find fonts for: CJK"));
+
+                nsAutoTArray<nsRefPtr<FontEntry>, 15> fonts;
+                this->GetCJKPrefFonts(fonts);
+                selectedFont = WhichFontSupportsChar(fonts, ch);
+            } else {
+                const char *langGroup = LangGroupFromUnicodeRange(unicodeRange);
+                if (langGroup) {
+                    PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Trying to find fonts for: %s", langGroup));
+
+                    nsAutoTArray<nsRefPtr<FontEntry>, 5> fonts;
+                    this->GetPrefFonts(langGroup, fonts);
+                    selectedFont = WhichFontSupportsChar(fonts, ch);
+                }
+            }
+        }
+    }
+
+    // before searching for something else check the font used for the previous character
+    if (!selectedFont && aFont && HasCharacter(aFont, ch))
+        selectedFont = aFont;
+
+    // otherwise look for other stuff
+    if (!selectedFont) {
+        PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Looking for best match"));
+        
+        nsRefPtr<gfxWindowsFont> refFont = mGroup->GetFontAt(0);
+        gfxWindowsPlatform *platform = gfxWindowsPlatform::GetPlatform();
+        selectedFont = platform->FindFontForChar(ch, refFont);
+    }
+
+    return selectedFont;
+#endif
+}
+
+PRUint32
+gfxQtFontGroup::ComputeRanges()
+{
+    const PRUnichar *str = mString.get();
+    PRUint32 len = mString.Length();
+
+    mRanges.Clear();
+
+    PRUint32 prevCh = 0;
+    for (PRUint32 i = 0; i < len; i++) {
+        const PRUint32 origI = i; // save off incase we increase for surrogate
+        PRUint32 ch = str[i];
+        if ((i+1 < len) && NS_IS_HIGH_SURROGATE(ch) && NS_IS_LOW_SURROGATE(str[i+1])) {
+            i++;
+            ch = SURROGATE_TO_UCS4(ch, str[i]);
+        }
+
+        PRUint32 nextCh = 0;
+        if (i+1 < len) {
+            nextCh = str[i+1];
+            if ((i+2 < len) && NS_IS_HIGH_SURROGATE(ch) && NS_IS_LOW_SURROGATE(str[i+2]))
+                nextCh = SURROGATE_TO_UCS4(nextCh, str[i+2]);
+        }
+        gfxQtFont *fe = FindFontForChar(ch,
+                                        prevCh,
+                                        nextCh,
+                                        (mRanges.Length() == 0) ? nsnull : mRanges[mRanges.Length() - 1].font);
+
+        prevCh = ch;
+
+        if (mRanges.Length() == 0) {
+            TextRange r(0,1);
+            r.font = fe;
+            mRanges.AppendElement(r);
+        } else {
+            TextRange& prevRange = mRanges[mRanges.Length() - 1];
+            if (prevRange.font != fe) {
+                // close out the previous range
+                prevRange.end = origI;
+
+                TextRange r(origI, i+1);
+                r.font = fe;
+                mRanges.AppendElement(r);
+            }
+        }
+    }
+    mRanges[mRanges.Length()-1].end = len;
+
+    PRUint32 nranges = mRanges.Length();
+    return nranges;
+}
+
+void gfxQtFontGroup::CreateGlyphRunsFT(gfxTextRun *aTextRun)
+{
+#if 0
+    QString str(aUTF8, aUTF8Length);
+    QStackTextEngine engine(str, mQFont);
+    const Qt::LayoutDirection dir = aTextRun->IsRightToLeft() ? Qt::RightToLeft : Qt::LeftTRight;
+    engine.option.setTextDirection(dir);
+    engine.ignoreBidi = true;
+
+    // itemize
+    engine.itemize();
+
+
+    // XXX i think at this point we want to create a new textengine for each item
+    
+    // ...
+    QScriptLine line;
+    line.length = str.length();
+    engine.shapeLine(line);
+
+    int nItems = engine.layoutData->items.size();
+    QVarLengthArray<int> visualOrder(nItems);
+    QVarLengthArray<uchar> levels(nItems);
+    for (int i = 0; i < nItems; ++i)
+        levels[i] = engine.layoutData->items[i].analysis.bidiLevel;
+    QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
+
+    QFixed x = QFixed::fromReal(p.x());
+    QFixed ox = x;
+
+    for (int i = 0; i < nItems; ++i) {
+        int item = visualOrder[i];
+        const QScriptItem &si = engine.layoutData->items.at(item);
+        if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
+            x += si.width;
+            continue;
+        }
+        QFont f = engine.font(si);
+        /*
+          QTextItemInt gf(si, &f);
+          gf.num_glyphs = si.num_glyphs;
+          gf.glyphs = engine.glyphs(&si);
+          gf.chars = engine.layoutData->string.unicode() + si.position;
+          gf.num_chars = engine.length(item);
+          gf.width = si.width;
+          gf.logClusters = engine.logClusters(&si);
+
+          // drawTextItem(QPointF(x.toReal(), p.y()), gf);
+        */
+
+        const PRUint8 *p = aUTF8;
+        PRUint32 utf16Offset = 0;
+        gfxTextRun::CompressedGlyph g;
+
+        aTextRun->AddGlyphRun(font, 0);
+        // a textRun likely has the same font for most of the characters, so we can
+        // lock it before the loop for efficiency
+        FT_Face face =  font->GetQFont().freetypeFace();
+        while (p < aUTF8 + aUTF8Length) {
+            // convert UTF-8 character and step to the next one in line
+            PRUint8 chLen;
+        }
+        if (advance >= 0 &&
+            gfxTextRun::CompressedGlyph::IsSimpleAdvance(advance) &&
+            gfxTextRun::CompressedGlyph::IsSimpleGlyphID(gid))
+            {
+                aTextRun->SetSimpleGlyph(utf16Offset,
+                                         g.SetSimpleGlyph(advance, gid));
+                glyphFound = PR_TRUE;
+            } else if (gid == 0) {
+            // gid = 0 only happens when the glyph is missing from the font
+            if (i == fontlistLast) {
+                // set the missing glyph only when it's missing from the very
+                // last font
+                aTextRun->SetMissingGlyph(utf16Offset, ch);
+            }
+            glyphFound = PR_FALSE;
+        } else {
+            gfxTextRun::DetailedGlyph details;
+            details.mGlyphID = gid;
+            NS_ASSERTION(details.mGlyphID == gid, "Seriously weird glyph ID detected!");
+            details.mAdvance = advance;
+            details.mXOffset = 0;
+            details.mYOffset = 0;
+            g.SetComplex(aTextRun->IsClusterStart(utf16Offset), PR_TRUE, 1);
+            aTextRun->SetGlyphs(utf16Offset, g, &details);
+            glyphFound = PR_TRUE;
+        }
+
+        x += si.width;
+    }
+#endif
+
+    ComputeRanges();
+
+    const PRUnichar *strStart = mString.get();
+    for (PRUint32 i = 0; i < mRanges.Length(); ++i) {
+        const TextRange& range = mRanges[i];
+        const PRUnichar *rangeString = strStart + range.start;
+        PRUint32 rangeLength = range.Length();
+
+        gfxQtFont *font = range.font ? range.font.get() : GetFontAt(0);
+        AddRange(aTextRun, font, rangeString, rangeLength);
+    }
+    
+}
+
+void
+gfxQtFontGroup::AddRange(gfxTextRun *aTextRun, gfxQtFont *font, const PRUnichar *str, PRUint32 len)
+{
+    const PRUint32 appUnitsPerDevUnit = aTextRun->GetAppUnitsPerDevUnit();
+    // we'll pass this in/figure it out dynamically, but at this point there can be only one face.
+    FT_Face face = cairo_ft_scaled_font_lock_face(font->CairoScaledFont());
+
+    gfxTextRun::CompressedGlyph g;
+
+    aTextRun->AddGlyphRun(font, 0);
+    for (PRUint32 i = 0; i < len; i++) {
+        PRUint32 ch = str[i];
+
+        if (ch == 0) {
+            // treat this null byte as a missing glyph, don't create a glyph for it
+            aTextRun->SetMissingGlyph(i, 0);
+            continue;
+        }
+
+        NS_ASSERTION(!IsInvalidChar(ch), "Invalid char detected");
+        FT_UInt gid = FT_Get_Char_Index(face, ch); // find the glyph id
+        PRInt32 advance = 0;
+
+        if (gid == font->GetSpaceGlyph()) {
+            advance = (int)(font->GetMetrics().spaceWidth * appUnitsPerDevUnit);
+        } else if (gid == 0) {
+            advance = -1; // trigger the missing glyphs case below
+        } else {
+            // find next character and its glyph -- in case they exist
+            // and exist in the current font face -- to compute kerning
+            PRUint32 chNext = 0;
+            FT_UInt gidNext = 0;
+            FT_Pos lsbDeltaNext = 0;
+
+            if (FT_HAS_KERNING(face) && i + 1 < len) {
+                chNext = str[i+1];
+                if (chNext != 0) {
+                    gidNext = FT_Get_Char_Index(face, chNext);
+                    if (gidNext && gidNext != font->GetSpaceGlyph()) {
+                        FT_Load_Glyph(face, gidNext, FT_LOAD_DEFAULT);
+                        lsbDeltaNext = face->glyph->lsb_delta;
+                    }
+                }
+            }
+
+            // now load the current glyph
+            FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT); // load glyph into the slot
+            advance = face->glyph->advance.x;
+
+            // now add kerning to the current glyph's advance
+            if (chNext && gidNext) {
+                FT_Vector kerning; kerning.x = 0;
+                FT_Get_Kerning(face, gid, gidNext, FT_KERNING_DEFAULT, &kerning);
+                advance += kerning.x;
+                if (face->glyph->rsb_delta - lsbDeltaNext >= 32) {
+                    advance -= 64;
+                } else if (face->glyph->rsb_delta - lsbDeltaNext < -32) {
+                    advance += 64;
+                }
+            }
+
+            // now apply unit conversion and scaling
+            advance = (advance >> 6) * appUnitsPerDevUnit;
+        }
+#ifdef DEBUG_thebes_2
+        printf(" gid=%d, advance=%d (%s)\n", gid, advance,
+               NS_LossyConvertUTF16toASCII(font->GetName()).get());
+#endif
+
+        if (advance >= 0 &&
+            gfxTextRun::CompressedGlyph::IsSimpleAdvance(advance) &&
+            gfxTextRun::CompressedGlyph::IsSimpleGlyphID(gid)) {
+            aTextRun->SetSimpleGlyph(i, g.SetSimpleGlyph(advance, gid));
+        } else if (gid == 0) {
+            // gid = 0 only happens when the glyph is missing from the font
+            aTextRun->SetMissingGlyph(i, ch);
+        } else {
+            gfxTextRun::DetailedGlyph details;
+            details.mGlyphID = gid;
+            NS_ASSERTION(details.mGlyphID == gid, "Seriously weird glyph ID detected!");
+            details.mAdvance = advance;
+            details.mXOffset = 0;
+            details.mYOffset = 0;
+            g.SetComplex(aTextRun->IsClusterStart(i), PR_TRUE, 1);
+            aTextRun->SetGlyphs(i, g, &details);
+        }
+    }
+
+    cairo_ft_scaled_font_unlock_face(font->CairoScaledFont());
+}
+
+/**
+ * gfxQtFont
+ */
+gfxQtFont::gfxQtFont(FontEntry *aFontEntry,
+                     const gfxFontStyle *aFontStyle)
+    : gfxFont(aFontEntry, aFontStyle),
+    mScaledFont(nsnull),
+    mHasSpaceGlyph(PR_FALSE),
+    mSpaceGlyph(0),
+    mHasMetrics(PR_FALSE),
+    mAdjustedSize(0)
+{
+    mFontEntry = aFontEntry;
+    NS_ASSERTION(mFontEntry, "Unable to find font entry for font.  Something is whack.");
+}
+
+gfxQtFont::~gfxQtFont()
+{
+    if (mScaledFont) {
+        cairo_scaled_font_destroy(mScaledFont);
+        mScaledFont = nsnull;
+    }
+}
+
+// rounding and truncation functions for a Freetype floating point number 
+// (FT26Dot6) stored in a 32bit integer with high 26 bits for the integer
+// part and low 6 bits for the fractional part. 
+#define MOZ_FT_ROUND(x) (((x) + 32) & ~63) // 63 = 2^6 - 1
+#define MOZ_FT_TRUNC(x) ((x) >> 6)
+#define CONVERT_DESIGN_UNITS_TO_PIXELS(v, s) \
+        MOZ_FT_TRUNC(MOZ_FT_ROUND(FT_MulFix((v) , (s))))
+
+const gfxFont::Metrics&
+gfxQtFont::GetMetrics()
+{
+    if (mHasMetrics)
+        return mMetrics;
+
+    mMetrics.emHeight = GetStyle()->size;
+
+    FT_Face face = cairo_ft_scaled_font_lock_face(CairoScaledFont());
+
+    if (!face) {
+        // Abort here already, otherwise we crash in the following
+        // this can happen if the font-size requested is zero.
+        // The metrics will be incomplete, but then we don't care.
+        return mMetrics;
+    }
+
+    mMetrics.emHeight = GetStyle()->size;
+
+    FT_UInt gid; // glyph ID
+
+    const double emUnit = 1.0 * face->units_per_EM;
+    const double xScale = face->size->metrics.x_ppem / emUnit;
+    const double yScale = face->size->metrics.y_ppem / emUnit;
+
+    // properties of space
+    gid = FT_Get_Char_Index(face, ' ');
+    if (gid) {
+        FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT);
+        // face->glyph->metrics.width doesn't work for spaces, use advance.x instead
+        mMetrics.spaceWidth = face->glyph->advance.x >> 6;
+        // save the space glyph
+        mSpaceGlyph = gid;
+    } else {
+        NS_ASSERTION(0, "blah");
+    }
+            
+    // properties of 'x', also use its width as average width
+    gid = FT_Get_Char_Index(face, 'x'); // select the glyph
+    if (gid) {
+        // Load glyph into glyph slot. Here, use no_scale to get font units.
+        FT_Load_Glyph(face, gid, FT_LOAD_NO_SCALE);
+        mMetrics.xHeight = face->glyph->metrics.height * yScale;
+        mMetrics.aveCharWidth = face->glyph->metrics.width * xScale;
+    } else {
+        // this font doesn't have an 'x'...
+        // fake these metrics using a fraction of the font size
+        mMetrics.xHeight = mMetrics.emHeight * 0.5;
+        mMetrics.aveCharWidth = mMetrics.emHeight * 0.5;
+    }
+
+    // compute an adjusted size if we need to
+    if (mAdjustedSize == 0 && GetStyle()->sizeAdjust != 0) {
+        gfxFloat aspect = mMetrics.xHeight / GetStyle()->size;
+        mAdjustedSize = GetStyle()->GetAdjustedSize(aspect);
+        mMetrics.emHeight = mAdjustedSize;
+    }
+
+    // now load the OS/2 TrueType table to load access some more properties
+    TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
+    if (os2 && os2->version != 0xFFFF) { // should be there if not old Mac font
+        // if we are here we can improve the avgCharWidth
+        mMetrics.aveCharWidth = os2->xAvgCharWidth * xScale;
+
+        mMetrics.superscriptOffset = os2->ySuperscriptYOffset * yScale;
+        mMetrics.superscriptOffset = PR_MAX(1, mMetrics.superscriptOffset);
+        // some fonts have the incorrect sign (from gfxPangoFonts)
+        mMetrics.subscriptOffset   = fabs(os2->ySubscriptYOffset * yScale);
+        mMetrics.subscriptOffset   = PR_MAX(1, fabs(mMetrics.subscriptOffset));
+        mMetrics.strikeoutOffset   = os2->yStrikeoutPosition * yScale;
+        mMetrics.strikeoutSize     = os2->yStrikeoutSize * yScale;
+    } else {
+        // use fractions of emHeight instead of xHeight for these to be more robust
+        mMetrics.superscriptOffset = mMetrics.emHeight * 0.5;
+        mMetrics.subscriptOffset   = mMetrics.emHeight * 0.2;
+        mMetrics.strikeoutOffset   = mMetrics.emHeight * 0.3;
+        mMetrics.strikeoutSize     = face->underline_thickness * yScale;
+    }
+    // seems that underlineOffset really has to be negative
+    mMetrics.underlineOffset = face->underline_position * yScale;
+    mMetrics.underlineSize   = face->underline_thickness * yScale;
+
+    // descents are negative in FT but Thebes wants them positive
+    mMetrics.emAscent        = face->ascender * yScale;
+    mMetrics.emDescent       = -face->descender * yScale;
+    mMetrics.maxHeight       = face->height * yScale;
+    mMetrics.maxAscent       = face->bbox.yMax * yScale;
+    mMetrics.maxDescent      = -face->bbox.yMin * yScale;
+    mMetrics.maxAdvance      = face->max_advance_width * xScale;
+    // leading are not available directly (only for WinFNTs)
+    double lineHeight = mMetrics.maxAscent + mMetrics.maxDescent;
+    if (lineHeight > mMetrics.emHeight) {
+        mMetrics.internalLeading = lineHeight - mMetrics.emHeight;
+    } else {
+        mMetrics.internalLeading = 0;
+    }
+    mMetrics.externalLeading = 0; // normal value for OS/2 fonts, too
+
+    SanitizeMetrics(&mMetrics, PR_FALSE);
+
+    /*
+    printf("gfxOS2Font[%#x]::GetMetrics():\n"
+           "  emHeight=%f == %f=gfxFont::style.size == %f=adjSz\n"
+           "  maxHeight=%f  xHeight=%f\n"
+           "  aveCharWidth=%f==xWidth  spaceWidth=%f\n"
+           "  supOff=%f SubOff=%f   strOff=%f strSz=%f\n"
+           "  undOff=%f undSz=%f    intLead=%f extLead=%f\n"
+           "  emAsc=%f emDesc=%f maxH=%f\n"
+           "  maxAsc=%f maxDes=%f maxAdv=%f\n",
+           (unsigned)this,
+           mMetrics.emHeight, GetStyle()->size, mAdjustedSize,
+           mMetrics.maxHeight, mMetrics.xHeight,
+           mMetrics.aveCharWidth, mMetrics.spaceWidth,
+           mMetrics.superscriptOffset, mMetrics.subscriptOffset,
+           mMetrics.strikeoutOffset, mMetrics.strikeoutSize,
+           mMetrics.underlineOffset, mMetrics.underlineSize,
+           mMetrics.internalLeading, mMetrics.externalLeading,
+           mMetrics.emAscent, mMetrics.emDescent, mMetrics.maxHeight,
+           mMetrics.maxAscent, mMetrics.maxDescent, mMetrics.maxAdvance
+          );
+    */
+
+    // XXX mMetrics.height needs to be set.
+    cairo_ft_scaled_font_unlock_face(CairoScaledFont());
+
+    mHasMetrics = PR_TRUE;
+    return mMetrics;
+}
+
+
+nsString
+gfxQtFont::GetUniqueName()
+{
+    return GetFontEntry()->Name();
+}
+
+PRUint32
+gfxQtFont::GetSpaceGlyph()
+{
+    NS_ASSERTION (GetStyle ()->size != 0,
+    "forgot to short-circuit a text run with zero-sized font?");
+
+    if(!mHasSpaceGlyph)
+    {
+        FT_UInt gid = 0; // glyph ID
+        FT_Face face = cairo_ft_scaled_font_lock_face(CairoScaledFont());
+        gid = FT_Get_Char_Index(face, ' ');
+        FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT);
+        mSpaceGlyph = gid;
+        mHasSpaceGlyph = PR_TRUE;
+        cairo_ft_scaled_font_unlock_face(CairoScaledFont());
+    }
+    return mSpaceGlyph;
+}
+
+FontEntry*
+gfxQtFont::GetFontEntry()
+{
+    return static_cast<FontEntry*> (mFontEntry.get());
+}
+
+cairo_font_face_t *
+gfxQtFont::CairoFontFace()
+{
+    // XXX we need to handle fake bold here (or by having a sepaerate font entry)
+    if (mStyle.weight >= 600 && GetFontEntry()->mWeight < 600)
+        printf("** We want fake weight\n");
+    return GetFontEntry()->CairoFontFace();
+}
+
+cairo_scaled_font_t *
+gfxQtFont::CairoScaledFont()
+{
+    if (!mScaledFont) {
+        cairo_matrix_t sizeMatrix;
+        cairo_matrix_t identityMatrix;
+
+        // XXX deal with adjusted size
+        cairo_matrix_init_scale(&sizeMatrix, mStyle.size, mStyle.size);
+        cairo_matrix_init_identity(&identityMatrix);
+
+        // synthetic oblique by skewing via the font matrix
+        PRBool needsOblique = (!GetFontEntry()->mItalic && (mStyle.style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)));
+
+        if (needsOblique) {
+            const double kSkewFactor = 0.25;
+
+            cairo_matrix_t style;
+            cairo_matrix_init(&style,
+                              1,                //xx
+                              0,                //yx
+                              -1 * kSkewFactor,  //xy
+                              1,                //yy
+                              0,                //x0
+                              0);               //y0
+            cairo_matrix_multiply(&sizeMatrix, &sizeMatrix, &style);
+        }
+
+        cairo_font_options_t *fontOptions = cairo_font_options_create();
+        mScaledFont = cairo_scaled_font_create(CairoFontFace(), &sizeMatrix,
+                                               &identityMatrix, fontOptions);
+        cairo_font_options_destroy(fontOptions);
+    }
+
+    NS_ASSERTION(mAdjustedSize == 0.0 ||
+                 cairo_scaled_font_status(mScaledFont) == CAIRO_STATUS_SUCCESS,
+                 "Failed to make scaled font");
+
+    return mScaledFont;
+}
+
+PRBool
+gfxQtFont::SetupCairoFont(gfxContext *aContext)
+{
+    cairo_scaled_font_t *scaledFont = CairoScaledFont();
+
+    if (cairo_scaled_font_status(scaledFont) != CAIRO_STATUS_SUCCESS) {
+        // Don't cairo_set_scaled_font as that would propagate the error to
+        // the cairo_t, precluding any further drawing.
+        return PR_FALSE;
+    }
+    cairo_set_scaled_font(aContext->GetCairo(), scaledFont);
+    return PR_TRUE;
+}
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/src/gfxQtNativeRenderer.cpp
@@ -0,0 +1,135 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Novell code.
+ *
+ * The Initial Developer of the Original Code is Novell.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   romaxa@gmail.com
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "gfxQtNativeRenderer.h"
+#include "gfxContext.h"
+
+#include "gfxQtPlatform.h"
+
+#include "cairo.h"
+#include <QWidget>
+
+typedef struct {
+    gfxQtNativeRenderer* mRenderer;
+    nsresult               mRV;
+} NativeRenderingClosure;
+
+
+static cairo_bool_t
+NativeRendering(void *closure,
+                QWidget * drawable,
+                short offset_x, short offset_y,
+                QRect * rectangles, unsigned int num_rects)
+{
+    NativeRenderingClosure* cl = (NativeRenderingClosure*)closure;
+    nsresult rv = cl->mRenderer->
+        NativeDraw(drawable, offset_x, offset_y,
+                   rectangles, num_rects);
+    cl->mRV = rv;
+    return NS_SUCCEEDED(rv);
+}
+
+
+nsresult
+gfxQtNativeRenderer::Draw(gfxContext* ctx, int width, int height,
+                          PRUint32 flags, DrawOutput* output)
+{
+    NativeRenderingClosure closure = { this, NS_OK };
+
+    if (output) {
+        output->mSurface = NULL;
+        output->mUniformAlpha = PR_FALSE;
+        output->mUniformColor = PR_FALSE;
+    }
+
+#if 0 // FIXME
+
+    cairo_gdk_drawing_result_t result;
+    // Make sure result.surface is null to start with; we rely on it
+    // being non-null meaning that a surface actually got allocated.
+    result.surface = NULL;
+
+    int cairoFlags = 0;
+    if (flags & DRAW_SUPPORTS_OFFSET) {
+        cairoFlags |= CAIRO_GDK_DRAWING_SUPPORTS_OFFSET;
+    }
+    if (flags & DRAW_SUPPORTS_CLIP_RECT) {
+        cairoFlags |= CAIRO_GDK_DRAWING_SUPPORTS_CLIP_RECT;
+    }
+    if (flags & DRAW_SUPPORTS_CLIP_LIST) {
+        cairoFlags |= CAIRO_GDK_DRAWING_SUPPORTS_CLIP_LIST;
+    }
+    if (flags & DRAW_SUPPORTS_ALTERNATE_SCREEN) {
+        cairoFlags |= CAIRO_GDK_DRAWING_SUPPORTS_ALTERNATE_SCREEN;
+    }
+    if (flags & DRAW_SUPPORTS_NONDEFAULT_VISUAL) {
+        cairoFlags |= CAIRO_GDK_DRAWING_SUPPORTS_NONDEFAULT_VISUAL;
+    }
+
+    cairo_draw_with_gdk(ctx->GetCairo(),
+                        gfxPlatformGtk::GetPlatform()->GetGdkDrawable(ctx->OriginalSurface()),
+                        NativeRendering, 
+                        &closure, width, height,
+                        (flags & DRAW_IS_OPAQUE) ? CAIRO_GDK_DRAWING_OPAQUE : CAIRO_GDK_DRAWING_TRANSPARENT,
+                        (cairo_gdk_drawing_support_t)cairoFlags,
+                        output ? &result : NULL);
+
+    if (NS_FAILED(closure.mRV)) {
+        if (result.surface) {
+            NS_ASSERTION(output, "How did that happen?");
+            cairo_surface_destroy (result.surface);
+        }
+        return closure.mRV;
+    }
+
+    if (output) {
+        if (result.surface) {
+            output->mSurface = gfxASurface::Wrap(result.surface);
+            if (!output->mSurface) {
+                cairo_surface_destroy (result.surface);
+                return NS_ERROR_OUT_OF_MEMORY;
+            }
+        }
+
+        output->mUniformAlpha = result.uniform_alpha;
+        output->mUniformColor = result.uniform_color;
+        output->mColor = gfxRGBA(result.r, result.g, result.b, result.alpha);
+    }
+#endif
+
+    return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/src/gfxQtPlatform.cpp
@@ -0,0 +1,389 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Foundation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir@pobox.com>
+ *   Masayuki Nakano <masayuki@d-toybox.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <QPixmap>
+#include <QX11Info>
+#include <QApplication>
+#include <QWidget>
+
+#include "gfxQtPlatform.h"
+
+#include "gfxFontconfigUtils.h"
+
+#include "cairo.h"
+
+#include "gfxImageSurface.h"
+#include "gfxQPainterSurface.h"
+
+#include "gfxQtFonts.h"
+
+#include "nsUnicharUtils.h"
+
+#include <fontconfig/fontconfig.h>
+
+#include "nsMathUtils.h"
+
+#include "lcms.h"
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+PRInt32 gfxQtPlatform::sDPI = -1;
+gfxFontconfigUtils *gfxQtPlatform::sFontconfigUtils = nsnull;
+static cairo_user_data_key_t cairo_qt_pixmap_key;
+static void do_qt_pixmap_unref (void *data)
+{
+    QPixmap *pmap = (QPixmap*)data;
+    delete pmap;
+}
+
+typedef nsDataHashtable<nsStringHashKey, nsRefPtr<FontFamily> > FontTable;
+static FontTable *gPlatformFonts = NULL;
+static FontTable *gPlatformFontAliases = NULL;
+static FT_Library gPlatformFTLibrary = NULL;
+
+
+gfxQtPlatform::gfxQtPlatform()
+{
+    if (!sFontconfigUtils)
+        sFontconfigUtils = gfxFontconfigUtils::GetFontconfigUtils();
+
+
+    FT_Init_FreeType(&gPlatformFTLibrary);
+
+    gPlatformFonts = new FontTable();
+    gPlatformFonts->Init(100);
+    gPlatformFontAliases = new FontTable();
+    gPlatformFontAliases->Init(100);
+    UpdateFontList();
+
+    InitDPI();
+}
+
+gfxQtPlatform::~gfxQtPlatform()
+{
+    gfxFontconfigUtils::Shutdown();
+    sFontconfigUtils = nsnull;
+
+    delete gPlatformFonts;
+    gPlatformFonts = NULL;
+    delete gPlatformFontAliases;
+    gPlatformFontAliases = NULL;
+
+    cairo_debug_reset_static_data();
+
+    FT_Done_FreeType(gPlatformFTLibrary);
+    gPlatformFTLibrary = NULL;
+
+
+#if 0
+    // It would be nice to do this (although it might need to be after
+    // the cairo shutdown that happens in ~gfxPlatform).  It even looks
+    // idempotent.  But it has fatal assertions that fire if stuff is
+    // leaked, and we hit them.
+    FcFini();
+#endif
+}
+
+already_AddRefed<gfxASurface>
+gfxQtPlatform::CreateOffscreenSurface(const gfxIntSize& size,
+                                      gfxASurface::gfxImageFormat imageFormat)
+{
+    nsRefPtr<gfxASurface> newSurface =
+        new gfxQPainterSurface (size, gfxASurface::ContentFromFormat(imageFormat));
+
+    return newSurface.forget();
+}
+
+nsresult
+gfxQtPlatform::GetFontList(const nsACString& aLangGroup,
+                            const nsACString& aGenericFamily,
+                            nsStringArray& aListOfFonts)
+{
+    return sFontconfigUtils->GetFontList(aLangGroup, aGenericFamily,
+                                         aListOfFonts);
+}
+
+nsresult
+gfxQtPlatform::UpdateFontList()
+{
+    FcPattern *pat = NULL;
+    FcObjectSet *os = NULL;
+    FcFontSet *fs = NULL;
+    PRInt32 result = -1;
+
+    pat = FcPatternCreate();
+    os = FcObjectSetBuild(FC_FAMILY, FC_FILE, FC_INDEX, FC_WEIGHT, FC_SLANT, FC_WIDTH, NULL);
+
+    fs = FcFontList(NULL, pat, os);
+
+
+    for (int i = 0; i < fs->nfont; i++) {
+        char *str;
+
+        if (FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, (FcChar8 **) &str) != FcResultMatch)
+            continue;
+
+        printf("Family: %s\n", str);
+
+        nsAutoString name(NS_ConvertUTF8toUTF16(nsDependentCString(str)).get());
+        nsAutoString key(name);
+        ToLowerCase(key);
+        nsRefPtr<FontFamily> ff;
+        if (!gPlatformFonts->Get(key, &ff)) {
+            ff = new FontFamily(name);
+            gPlatformFonts->Put(key, ff);
+        }
+
+        nsRefPtr<FontEntry> fe = new FontEntry(ff->Name());
+        ff->mFaces.AppendElement(fe);
+
+        if (FcPatternGetString(fs->fonts[i], FC_FILE, 0, (FcChar8 **) &str) == FcResultMatch) {
+            fe->mFilename = nsDependentCString(str);
+            printf(" - file: %s\n", str);
+        }
+
+        int x;
+        if (FcPatternGetInteger(fs->fonts[i], FC_INDEX, 0, &x) == FcResultMatch) {
+            printf(" - index: %d\n", x);
+            fe->mFTFontIndex = x;
+        } else {
+            fe->mFTFontIndex = 0;
+        }
+
+        if (FcPatternGetInteger(fs->fonts[i], FC_WEIGHT, 0, &x) == FcResultMatch) {
+            switch(x) {
+            case 0:
+                fe->mWeight = 100;
+                break;
+            case 40:
+                fe->mWeight = 200;
+                break;
+            case 50:
+                fe->mWeight = 300;
+                break;
+            case 75:
+            case 80:
+                fe->mWeight = 400;
+                break;
+            case 100:
+                fe->mWeight = 500;
+                break;
+            case 180:
+                fe->mWeight = 600;
+                break;
+            case 200:
+                fe->mWeight = 700;
+                break;
+            case 205:
+                fe->mWeight = 800;
+                break;
+            case 210:
+                fe->mWeight = 900;
+                break;
+            default:
+                // rough estimate
+                fe->mWeight = (((x * 4) + 100) / 100) * 100;
+                break;
+            }
+            printf(" - weight: %d\n", fe->mWeight);
+        }
+
+        fe->mItalic = PR_FALSE;
+        if (FcPatternGetInteger(fs->fonts[i], FC_SLANT, 0, &x) == FcResultMatch) {
+            switch (x) {
+            case FC_SLANT_ITALIC:
+            case FC_SLANT_OBLIQUE:
+                fe->mItalic = PR_TRUE;
+            }
+            printf(" - slant: %d\n", x);
+        }
+
+        if (FcPatternGetInteger(fs->fonts[i], FC_WIDTH, 0, &x) == FcResultMatch)
+            printf(" - width: %d\n", x);
+        // XXX deal with font-stretch stuff later
+    }
+
+    if (pat)
+        FcPatternDestroy(pat);
+    if (os)
+        FcObjectSetDestroy(os);
+    if (fs)
+        FcFontSetDestroy(fs);
+
+    return sFontconfigUtils->UpdateFontList();
+}
+
+nsresult
+gfxQtPlatform::ResolveFontName(const nsAString& aFontName,
+                                FontResolverCallback aCallback,
+                                void *aClosure,
+                                PRBool& aAborted)
+{
+
+    nsAutoString name(aFontName);
+    ToLowerCase(name);
+
+    nsRefPtr<FontFamily> ff;
+    if (gPlatformFonts->Get(name, &ff) ||
+        gPlatformFontAliases->Get(name, &ff)) {
+        aAborted = !(*aCallback)(ff->Name(), aClosure);
+        return NS_OK;
+    }
+
+    nsCAutoString utf8Name = NS_ConvertUTF16toUTF8(aFontName);
+
+    FcPattern *npat = FcPatternCreate();
+    FcPatternAddString(npat, FC_FAMILY, (FcChar8*)utf8Name.get());
+    FcObjectSet *nos = FcObjectSetBuild(FC_FAMILY, NULL);
+    FcFontSet *nfs = FcFontList(NULL, npat, nos);
+
+    for (int k = 0; k < nfs->nfont; k++) {
+        FcChar8 *str;
+        if (FcPatternGetString(nfs->fonts[k], FC_FAMILY, 0, (FcChar8 **) &str) != FcResultMatch)
+            continue;
+        nsAutoString altName = NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str)));
+        ToLowerCase(altName);
+        if (gPlatformFonts->Get(altName, &ff)) {
+            printf("Adding alias: %s -> %s\n", utf8Name.get(), str);
+            gPlatformFontAliases->Put(name, ff);
+            aAborted = !(*aCallback)(NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str))), aClosure);
+            goto DONE;
+        }
+    }
+
+    FcPatternDestroy(npat);
+    FcObjectSetDestroy(nos);
+    FcFontSetDestroy(nfs);
+
+    {
+    npat = FcPatternCreate();
+    FcPatternAddString(npat, FC_FAMILY, (FcChar8*)utf8Name.get());
+    FcPatternDel(npat, FC_LANG);
+    FcConfigSubstitute(NULL, npat, FcMatchPattern);
+    FcDefaultSubstitute(npat);
+
+    nos = FcObjectSetBuild(FC_FAMILY, NULL);
+    nfs = FcFontList(NULL, npat, nos);
+
+    FcResult fresult;
+
+    FcPattern *match = FcFontMatch(NULL, npat, &fresult);
+    if (match)
+        FcFontSetAdd(nfs, match);
+
+    for (int k = 0; k < nfs->nfont; k++) {
+        FcChar8 *str;
+        if (FcPatternGetString(nfs->fonts[k], FC_FAMILY, 0, (FcChar8 **) &str) != FcResultMatch)
+            continue;
+        nsAutoString altName = NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str)));
+        ToLowerCase(altName);
+        if (gPlatformFonts->Get(altName, &ff)) {
+            printf("Adding alias: %s -> %s\n", utf8Name.get(), str);
+            gPlatformFontAliases->Put(name, ff);
+            aAborted = !(*aCallback)(NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str))), aClosure);
+            goto DONE;
+        }
+    }
+    }
+ DONE:
+    FcPatternDestroy(npat);
+    FcObjectSetDestroy(nos);
+    FcFontSetDestroy(nfs);
+
+    return NS_OK;
+}
+
+nsresult
+gfxQtPlatform::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
+{
+    return sFontconfigUtils->GetStandardFamilyName(aFontName, aFamilyName);
+}
+
+gfxFontGroup *
+gfxQtPlatform::CreateFontGroup(const nsAString &aFamilies,
+                               const gfxFontStyle *aStyle)
+{
+    return new gfxQtFontGroup(aFamilies, aStyle);
+}
+
+/* static */
+void
+gfxQtPlatform::InitDPI()
+{
+    if (sDPI <= 0) {
+        // Fall back to something sane
+        sDPI = 96;
+    }
+}
+
+cmsHPROFILE
+gfxQtPlatform::GetPlatformCMSOutputProfile()
+{
+    return nsnull;
+}
+
+
+FT_Library
+gfxQtPlatform::GetFTLibrary()
+{
+    return gPlatformFTLibrary;
+}
+
+FontFamily *
+gfxQtPlatform::FindFontFamily(const nsAString& aName)
+{
+    nsAutoString name(aName);
+    ToLowerCase(name);
+
+    nsRefPtr<FontFamily> ff;
+    if (!gPlatformFonts->Get(name, &ff)) {
+        return nsnull;
+    }
+    return ff.get();
+}
+
+FontEntry *
+gfxQtPlatform::FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontStyle)
+{
+    nsRefPtr<FontFamily> ff = FindFontFamily(aName);
+    if (!ff)
+        return nsnull;
+
+    return ff->FindFontEntry(aFontStyle);
+}
--- a/layout/build/Makefile.in
+++ b/layout/build/Makefile.in
@@ -237,16 +237,21 @@ EXTRA_DSO_LDOPTS = \
 		$(NULL)
 
 ifdef MOZ_ENABLE_GTK2
 EXTRA_DSO_LDOPTS += $(MOZ_GTK2_LIBS) \
 		    -lXrender \
 		    $(NULL)
 endif
 
+ifdef MOZ_ENABLE_QT
+EXTRA_DSO_LDOPTS += $(MOZ_QT_LIBS) \
+		    $(NULL)
+endif
+
 ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
 EXTRA_DSO_LDOPTS += \
 	$(TK_LIBS) \
 	$(NULL)
 endif
 
 # Add explicit X11 dependency when building against X11 toolkits
 ifneq (,$(filter gtk2,$(MOZ_WIDGET_TOOLKIT)))
--- a/layout/generic/Makefile.in
+++ b/layout/generic/Makefile.in
@@ -191,16 +191,20 @@ LOCAL_INCLUDES += \
 		-I$(srcdir)/../../dom/src/base \
 		$(MOZ_CAIRO_CFLAGS) \
 		$(NULL)
 
 ifdef MOZ_ENABLE_GTK2
 CXXFLAGS += $(MOZ_GTK2_CFLAGS)
 endif
 
+ifdef MOZ_ENABLE_QT
+CXXFLAGS += $(MOZ_QT_CFLAGS)
+endif
+
 libs::
 	$(INSTALL) $(RESOURCES_HTML) $(DIST)/bin/res/html
 	$(INSTALL) $(RESOURCES) $(DIST)/bin/res
 
 install::
 	$(SYSINSTALL) $(IFLAGS1) $(RESOURCES_HTML) $(DESTDIR)$(mozappdir)/res/html
 	$(SYSINSTALL) $(IFLAGS1) $(RESOURCES) $(DESTDIR)$(mozappdir)/res
 
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -49,16 +49,22 @@
 #include "nscore.h"
 #include "nsCOMPtr.h"
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsWidgetsCID.h"
 #include "nsIView.h"
 #include "nsIViewManager.h"
 #include "nsIDOMKeyListener.h"
+#ifdef MOZ_X11
+#ifdef MOZ_WIDGET_QT
+#include <QWidget>
+#include <QX11Info>
+#endif
+#endif
 #include "nsIPluginHost.h"
 #include "nsplugin.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "prmem.h"
 #include "nsGkAtoms.h"
 #include "nsIAppShell.h"
 #include "nsIDocument.h"
@@ -164,16 +170,20 @@ enum { XKeyPress = KeyPress };
 #include <gdk/gdkx.h>
 #endif
 #endif
 
 #ifdef MOZ_WIDGET_GTK2
 #include "gfxGdkNativeRenderer.h"
 #endif
 
+#ifdef MOZ_WIDGET_QT
+#include "gfxQtNativeRenderer.h"
+#endif
+
 #ifdef XP_WIN
 #include <wtypes.h>
 #include <winuser.h>
 #endif
 
 #ifdef CreateEvent // Thank you MS.
 #undef CreateEvent
 #endif
@@ -475,32 +485,48 @@ private:
   nsRefPtr<nsPluginDOMContextMenuListener> mCXMenuListener;
 
   nsresult DispatchKeyToPlugin(nsIDOMEvent* aKeyEvent);
   nsresult DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent);
   nsresult DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent);
 
   nsresult EnsureCachedAttrParamArrays();
 
-#ifdef MOZ_WIDGET_GTK2
+#if defined(MOZ_WIDGET_GTK2)
   class Renderer : public gfxGdkNativeRenderer {
   public:
     Renderer(nsPluginWindow* aWindow, nsIPluginInstance* aInstance,
              const nsIntSize& aPluginSize, const nsIntRect& aDirtyRect)
       : mWindow(aWindow), mInstance(aInstance),
         mPluginSize(aPluginSize), mDirtyRect(aDirtyRect)
     {}
     virtual nsresult NativeDraw(GdkDrawable * drawable, short offsetX, 
             short offsetY, GdkRectangle * clipRects, PRUint32 numClipRects);
   private:
     nsPluginWindow* mWindow;
     nsIPluginInstance* mInstance;
     const nsIntSize& mPluginSize;
     const nsIntRect& mDirtyRect;
   };
+#elif defined(MOZ_WIDGET_QT)
+  class Renderer : public gfxQtNativeRenderer {
+  public:
+    Renderer(nsPluginWindow* aWindow, nsIPluginInstance* aInstance,
+             const nsIntSize& aPluginSize, const nsIntRect& aDirtyRect)
+      : mWindow(aWindow), mInstance(aInstance),
+        mPluginSize(aPluginSize), mDirtyRect(aDirtyRect)
+    {}
+    virtual nsresult NativeDraw(QWidget * drawable, short offsetX, 
+            short offsetY, QRect * clipRects, PRUint32 numClipRects);
+  private:
+    nsPluginWindow* mWindow;
+    nsIPluginInstance* mInstance;
+    const nsIntSize& mPluginSize;
+    const nsIntRect& mDirtyRect;
+  };
 #endif
 
 };
 
 #if defined(XP_WIN) || (defined(DO_DIRTY_INTERSECT) && defined(XP_MACOSX)) || defined(XP_OS2)
 static void ConvertAppUnitsToPixels(const nsPresContext& aPresContext, const nsRect& aTwipsRect, nsIntRect& aPixelRect);
 #endif
 
@@ -4124,28 +4150,43 @@ DepthOfVisual(const Screen* screen, cons
     }
   }
 
   NS_ERROR("Visual not on Screen.");
   return 0;
 }
 #endif
 
+#if defined(MOZ_WIDGET_GTK2)
 nsresult
 nsPluginInstanceOwner::Renderer::NativeDraw(GdkDrawable * drawable, 
                                             short offsetX, short offsetY,
                                             GdkRectangle * clipRects, 
                                             PRUint32 numClipRects)
 
 {
 #ifdef MOZ_X11
   Visual * visual = GDK_VISUAL_XVISUAL(gdk_drawable_get_visual(drawable));
   Colormap colormap = GDK_COLORMAP_XCOLORMAP(gdk_drawable_get_colormap(drawable));
   Screen * screen = GDK_SCREEN_XSCREEN (gdk_drawable_get_screen(drawable));
 #endif
+#elif defined(MOZ_WIDGET_QT)
+nsresult
+nsPluginInstanceOwner::Renderer::NativeDraw(QWidget * drawable,
+                                            short offsetX, short offsetY,
+                                            QRect * clipRects,
+                                            PRUint32 numClipRects)
+{
+#ifdef MOZ_X11
+  QX11Info xinfo = drawable->x11Info();
+  Visual * visual = (Visual*) xinfo.visual();
+  Colormap colormap = xinfo.colormap();
+  Screen * screen = (Screen*) xinfo.screen();
+#endif
+#endif
   // See if the plugin must be notified of new window parameters.
   PRBool doupdatewindow = PR_FALSE;
 
   if (mWindow->x != offsetX || mWindow->y != offsetY) {
     mWindow->x = offsetX;
     mWindow->y = offsetY;
     doupdatewindow = PR_TRUE;
   }
@@ -4155,20 +4196,27 @@ nsPluginInstanceOwner::Renderer::NativeD
     mWindow->height = mPluginSize.height;
     doupdatewindow = PR_TRUE;
   }
 
   // The clip rect is relative to drawable top-left.
   NS_ASSERTION(numClipRects <= 1, "We don't support multiple clip rectangles!");
   nsIntRect clipRect;
   if (numClipRects) {
+#if defined(MOZ_WIDGET_GTK2)
     clipRect.x = clipRects[0].x;
     clipRect.y = clipRects[0].y;
     clipRect.width  = clipRects[0].width;
     clipRect.height = clipRects[0].height;
+#elif defined(MOZ_WIDGET_QT)
+    clipRect.x = clipRects[0].x();
+    clipRect.y = clipRects[0].y();
+    clipRect.width  = clipRects[0].width();
+    clipRect.height = clipRects[0].height();
+#endif
   }
   else {
     // nsPluginRect members are unsigned, but
     // we should have been given a clip if an offset is -ve.
     NS_ASSERTION(offsetX >= 0 && offsetY >= 0,
                  "Clip rectangle offsets are negative!");
     clipRect.x = offsetX;
     clipRect.y = offsetY;
@@ -4211,17 +4259,22 @@ nsPluginInstanceOwner::Renderer::NativeD
   if (!dirtyRect.IntersectRect(dirtyRect, clipRect))
     return NS_OK;
 
   nsPluginEvent pluginEvent;
   XGraphicsExposeEvent& exposeEvent = pluginEvent.event.xgraphicsexpose;
   // set the drawing info
   exposeEvent.type = GraphicsExpose;
   exposeEvent.display = DisplayOfScreen(screen);
-  exposeEvent.drawable = GDK_DRAWABLE_XID(drawable);
+  exposeEvent.drawable =
+#if defined(MOZ_WIDGET_GTK2)
+      GDK_DRAWABLE_XID(drawable);
+#elif defined(MOZ_WIDGET_QT)
+      drawable->x11PictureHandle();
+#endif
   exposeEvent.x = mDirtyRect.x + offsetX;
   exposeEvent.y = mDirtyRect.y + offsetY;
   exposeEvent.width  = mDirtyRect.width;
   exposeEvent.height = mDirtyRect.height;
   exposeEvent.count = 0;
   // information not set:
   exposeEvent.serial = 0;
   exposeEvent.send_event = False;
--- a/toolkit/Makefile.in
+++ b/toolkit/Makefile.in
@@ -55,16 +55,20 @@ DIRS	= \
 ifneq (,$(filter gtk2,$(MOZ_WIDGET_TOOLKIT)))
 DIRS += system/unixproxy
 endif
 
 ifneq (,$(filter cocoa,$(MOZ_WIDGET_TOOLKIT)))
 DIRS += system/osxproxy
 endif
 
+ifneq (,$(filter qt,$(MOZ_WIDGET_TOOLKIT)))
+DIRS += system/unixproxy
+endif
+
 ifdef MOZ_CRASHREPORTER
 DIRS += crashreporter
 endif
 
 DIRS += \
 	xre \
 	mozapps \
 	$(NULL)
--- a/toolkit/components/filepicker/Makefile.in
+++ b/toolkit/components/filepicker/Makefile.in
@@ -39,15 +39,15 @@
 DEPTH     = ../../..
 topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH     = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 ifdef MOZ_XUL
-ifeq (,$(filter beos os2 mac photon cocoa windows,$(MOZ_WIDGET_TOOLKIT)))
+ifeq (,$(filter qt beos os2 mac photon cocoa windows,$(MOZ_WIDGET_TOOLKIT)))
 DIRS = public src
 endif
 endif
 
 include $(topsrcdir)/config/rules.mk
 
--- a/toolkit/components/remote/Makefile.in
+++ b/toolkit/components/remote/Makefile.in
@@ -72,16 +72,20 @@ XPIDLSRCS = nsIRemoteService.idl
 ifneq (,$(filter gtk2,$(MOZ_WIDGET_TOOLKIT)))
 CPPSRCS += nsGTKRemoteService.cpp
 endif
 
 ifeq (photon,$(MOZ_WIDGET_TOOLKIT))
 CPPSRCS += nsPhRemoteService.cpp
 endif
 
+ifeq (qt,$(MOZ_WIDGET_TOOLKIT))
+CPPSRCS += nsQtRemoteService.cpp
+endif
+
 include $(topsrcdir)/config/rules.mk
 
 EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS) $(TK_LIBS)
 CXXFLAGS += $(TK_CFLAGS)
 
 # Add explicit X11 dependency when building against X11 toolkits
 ifneq (,$(filter gtk2,$(MOZ_WIDGET_TOOLKIT)))
 EXTRA_DSO_LDOPTS += $(XLDFLAGS) $(XLIBS)
new file mode 100644
--- /dev/null
+++ b/toolkit/components/remote/nsQtRemoteService.cpp
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=8:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *   Benjamin Smedberg <benjamin@smedbergs.us>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsQtRemoteService.h"
+
+#include <X11/Xatom.h> // for XA_STRING
+#include <stdlib.h>
+
+#include "nsIBaseWindow.h"
+#include "nsIDocShell.h"
+#include "nsPIDOMWindow.h"
+#include "nsIGenericFactory.h"
+#include "nsILocalFile.h"
+#include "nsIObserverService.h"
+#include "nsIServiceManager.h"
+#include "nsIWeakReference.h"
+#include "nsIWidget.h"
+#include "nsIAppShellService.h"
+#include "nsAppShellCID.h"
+
+#include "nsCOMPtr.h"
+#include "nsString.h"
+#include "prprf.h"
+#include "prenv.h"
+#include "nsCRT.h"
+
+#ifdef MOZ_WIDGET_GTK2
+//#include "nsGTKToolkit.h"
+#endif
+
+#ifdef MOZ_XUL_APP
+#include "nsICommandLineRunner.h"
+#include "nsXULAppAPI.h"
+#else
+#include "nsISuiteRemoteService.h"
+#endif
+
+#define MOZILLA_VERSION_PROP   "_MOZILLA_VERSION"
+#define MOZILLA_LOCK_PROP      "_MOZILLA_LOCK"
+#define MOZILLA_COMMAND_PROP   "_MOZILLA_COMMAND"
+#define MOZILLA_RESPONSE_PROP  "_MOZILLA_RESPONSE"
+#define MOZILLA_USER_PROP      "_MOZILLA_USER"
+#define MOZILLA_PROFILE_PROP   "_MOZILLA_PROFILE"
+#define MOZILLA_PROGRAM_PROP   "_MOZILLA_PROGRAM"
+#define MOZILLA_COMMANDLINE_PROP "_MOZILLA_COMMANDLINE"
+
+#ifdef IS_BIG_ENDIAN
+#define TO_LITTLE_ENDIAN32(x) \
+    ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
+    (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
+#else
+#define TO_LITTLE_ENDIAN32(x) (x)
+#endif
+
+#ifdef MOZ_XUL_APP
+const unsigned char kRemoteVersion[] = "5.1";
+#else
+const unsigned char kRemoteVersion[] = "5.0";
+#endif
+
+NS_IMPL_ISUPPORTS2(nsQtRemoteService,
+                   nsIRemoteService,
+                   nsIObserver)
+
+NS_IMETHODIMP
+nsQtRemoteService::Startup(const char* aAppName, const char* aProfileName)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+// #ifdef MOZ_WIDGET_GTK2
+// static nsGTKToolkit* GetGTKToolkit()
+// {
+//   nsCOMPtr<nsIAppShellService> svc = do_GetService(NS_APPSHELLSERVICE_CONTRACTID);
+//   if (!svc)
+//     return nsnull;
+//   nsCOMPtr<nsIDOMWindowInternal> window;
+//   svc->GetHiddenDOMWindow(getter_AddRefs(window));
+//   if (!window)
+//     return nsnull;
+//   nsIWidget* widget = GetMainWidget(window);
+//   if (!widget)
+//     return nsnull;
+//   nsIToolkit* toolkit = widget->GetToolkit();
+//   if (!toolkit)
+//     return nsnull;
+//   return static_cast<nsGTKToolkit*>(toolkit);
+// }
+// #endif
+
+NS_IMETHODIMP
+nsQtRemoteService::RegisterWindow(nsIDOMWindow* aWindow)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsQtRemoteService::Shutdown()
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsQtRemoteService::Observe(nsISupports* aSubject,
+                            const char *aTopic,
+                            const PRUnichar *aData)
+{
+  return NS_OK;
+}
+
+// {C0773E90-5799-4eff-AD03-3EBCD85624AC}
+#define NS_REMOTESERVICE_CID \
+  { 0xc0773e90, 0x5799, 0x4eff, { 0xad, 0x3, 0x3e, 0xbc, 0xd8, 0x56, 0x24, 0xac } }
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsQtRemoteService)
+
+static const nsModuleComponentInfo components[] =
+{
+  { "Remote Service",
+    NS_REMOTESERVICE_CID,
+    "@mozilla.org/toolkit/remote-service;1",
+    nsQtRemoteServiceConstructor
+  }
+};
+
+NS_IMPL_NSGETMODULE(RemoteServiceModule, components)
new file mode 100644
--- /dev/null
+++ b/toolkit/components/remote/nsQtRemoteService.h
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *   Benjamin Smedberg <benjamin@smedbergs.us>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __nsQtRemoteService_h__
+#define __nsQtRemoteService_h__
+
+#include "nsIRemoteService.h"
+
+#include "nsIObserver.h"
+
+#include "nsString.h"
+#include "nsInterfaceHashtable.h"
+
+class nsIDOMWindow;
+class nsIWeakReference;
+class nsIWidget;
+
+class nsQtRemoteService : public nsIRemoteService,
+                          public nsIObserver
+{
+public:
+  // We will be a static singleton, so don't use the ordinary methods.
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIREMOTESERVICE
+  NS_DECL_NSIOBSERVER
+
+  nsQtRemoteService() { };
+
+private:
+  ~nsQtRemoteService() { };
+};
+
+#endif // __nsQtRemoteService_h__
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -223,16 +223,21 @@ ifeq (gtk2,$(MOZ_WIDGET_TOOLKIT))
 EXTRA_DSO_LDOPTS += $(XLDFLAGS) $(XLIBS) $(MOZ_XFT_LIBS) $(MOZ_GTK2_LIBS) $(XT_LIBS) -lgthread-2.0
 EXTRA_DSO_LDOPTS += $(FT2_LIBS)
 endif
 
 ifdef NS_OSSO
 EXTRA_DSO_LDOPTS += -llocation -lgpsbt -losso
 endif
 
+ifeq (qt,$(MOZ_WIDGET_TOOLKIT))
+EXTRA_DSO_LDOPTS += $(XLDFLAGS) $(XLIBS) $(MOZ_XFT_LIBS) $(XT_LIBS) $(MOZ_QT_LIBS) -lgthread-2.0
+EXTRA_DSO_LDOPTS += $(FT2_LIBS)
+endif
+
 ifdef MOZ_ENABLE_STARTUP_NOTIFICATION
 EXTRA_DSO_LDOPTS += $(MOZ_STARTUP_NOTIFICATION_LIBS)
 endif
 
 ifeq ($(OS_ARCH),BeOS)
 EXTRA_DSO_LDOPTS += -lbe -ltracker
 endif
 
@@ -250,16 +255,20 @@ ifeq ($(OS_ARCH),WINCE)
 EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME, aygshell cellcore uuid ole32 oleaut32 )
 endif
 
 
 ifdef MOZ_JPROF
 EXTRA_DSO_LDOPTS += -ljprof
 endif
 
+ifdef MOZ_ENABLE_QT
+EXTRA_DSO_LDOPTS += $(MOZ_QT_LDFLAGS)
+endif
+
 ifdef MOZ_JAVAXPCOM
 dlldeps-javaxpcom.cpp: $(topsrcdir)/extensions/java/xpcom/src/dlldeps-javaxpcom.cpp
 	$(INSTALL) $^ .
 endif
 
 ifneq (,$(filter layout-debug,$(MOZ_EXTENSIONS)))
 DEFINES += -DMOZ_ENABLE_EXTENSION_LAYOUT_DEBUG
 endif
--- a/toolkit/library/libxul-config.mk
+++ b/toolkit/library/libxul-config.mk
@@ -156,16 +156,24 @@ endif
 endif
 
 ifneq (,$(filter cocoa,$(MOZ_WIDGET_TOOLKIT)))
 COMPONENT_LIBS += \
 	osxproxy \
 	$(NULL)
 endif
 
+ifdef MOZ_XUL
+ifeq (qt,$(MOZ_WIDGET_TOOLKIT))
+COMPONENT_LIBS += \
+        unixproxy \
+        $(NULL)
+endif
+endif
+
 ifdef MOZ_PERF_METRICS
 EXTRA_DSO_LIBS  += mozutil_s
 endif
 
 ifdef MOZ_XPINSTALL
 DEFINES += -DMOZ_XPINSTALL
 COMPONENT_LIBS += \
 	xpinstall \
@@ -221,17 +229,17 @@ COMPONENT_LIBS += \
 ifdef MOZ_XPFE_COMPONENTS
 COMPONENT_LIBS += \
 	windowds \
 	intlapp \
 	$(NULL)
 endif
 endif
 
-ifeq (,$(filter beos os2 mac photon cocoa windows,$(MOZ_WIDGET_TOOLKIT)))
+ifeq (,$(filter qt beos os2 mac photon cocoa windows,$(MOZ_WIDGET_TOOLKIT)))
 ifdef MOZ_XUL
 ifdef MOZ_XPFE_COMPONENTS
 COMPONENT_LIBS += fileview
 DEFINES += -DMOZ_FILEVIEW
 endif
 endif
 endif
 
@@ -309,16 +317,19 @@ ifeq (beos,$(MOZ_WIDGET_TOOLKIT))
 COMPONENT_LIBS += widget_beos
 endif
 ifeq (os2,$(MOZ_WIDGET_TOOLKIT))
 COMPONENT_LIBS += wdgtos2
 endif
 ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
 COMPONENT_LIBS += widget_mac
 endif
+ifeq (qt,$(MOZ_WIDGET_TOOLKIT))
+COMPONENT_LIBS += widget_qt
+endif
 
 ifdef MOZ_ENABLE_PHOTON
 COMPONENT_LIBS += widget_photon
 endif
 
 ifdef MOZ_OJI
 STATIC_LIBS += jsj
 COMPONENT_LIBS += oji
--- a/toolkit/library/nsStaticXULComponents.cpp
+++ b/toolkit/library/nsStaticXULComponents.cpp
@@ -88,16 +88,18 @@
 #elif defined(XP_BEOS)
 #  define WIDGET_MODULES MODULE(nsWidgetBeOSModule)
 #elif defined(XP_OS2)
 #  define WIDGET_MODULES MODULE(nsWidgetOS2Module)
 #elif defined(MOZ_WIDGET_GTK2)
 #  define WIDGET_MODULES MODULE(nsWidgetGtk2Module)
 #elif defined(MOZ_WIDGET_PHOTON)
 #  define WIDGET_MODULES MODULE(nsWidgetPhModule)
+#elif defined(MOZ_WIDGET_QT)
+#  define WIDGET_MODULES MODULE(nsWidgetQtModule)
 #else
 #  error Unknown widget module.
 #endif
 
 #ifdef ICON_DECODER
 #define ICON_MODULE MODULE(nsIconDecoderModule)
 #else
 #define ICON_MODULE
@@ -244,16 +246,19 @@
 #else
 #define XMLEXTRAS_MODULE
 #endif
 
 #ifdef MOZ_XUL
 #ifdef MOZ_ENABLE_GTK2
 #define UNIXPROXY_MODULE MODULE(nsUnixProxyModule)
 #endif
+#if defined(MOZ_WIDGET_QT)
+#define UNIXPROXY_MODULE MODULE(nsUnixProxyModule)
+#endif
 #endif
 #ifndef UNIXPROXY_MODULE
 #define UNIXPROXY_MODULE
 #endif
 
 #if defined(XP_MACOSX)
 #define OSXPROXY_MODULE MODULE(nsOSXProxyModule)
 #else
--- a/toolkit/themes/Makefile.in
+++ b/toolkit/themes/Makefile.in
@@ -50,17 +50,17 @@ include $(DEPTH)/config/autoconf.mk
 #                         GNOMEStripe overrides (toolkit/themes/gnomestripe)
 # OS/2                    Winstripe (toolkit/themes/winstripe) + 
 #                         PMStripe overrides (toolkit/themes/pmstripe)
 
 ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
 DIRS	= pinstripe
 else
 DIRS	= winstripe
-ifneq (,$(filter gtk2,$(MOZ_WIDGET_TOOLKIT)))
+ifneq (,$(filter gtk2 qt,$(MOZ_WIDGET_TOOLKIT)))
 DIRS    += gnomestripe
 endif
 ifneq (,$(filter os2,$(MOZ_WIDGET_TOOLKIT)))
 DIRS    += pmstripe
 endif
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/toolkit/toolkit-tiers.mk
+++ b/toolkit/toolkit-tiers.mk
@@ -263,16 +263,20 @@ ifndef BUILD_STATIC_LIBS
 tier_toolkit_dirs += toolkit/library
 endif
 endif
 
 ifdef MOZ_ENABLE_LIBXUL
 tier_toolkit_dirs += xpcom/stub
 endif
 
+ifneq (,$(MOZ_ENABLE_QT))
+tier_toolkit_dirs += embedding/browser/qt/tests
+endif
+
 ifdef NS_TRACE_MALLOC
 tier_toolkit_dirs += tools/trace-malloc
 endif
 
 ifdef MOZ_LDAP_XPCOM
 tier_toolkit_staticdirs += directory/c-sdk
 tier_toolkit_dirs	+= directory/xpcom
 endif
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -46,16 +46,21 @@
 #include <os2safe.h>
 #endif
 
 #define XPCOM_TRANSLATE_NSGM_ENTRY_POINT 1
 
 #include "nsAppRunner.h"
 #include "nsUpdateDriver.h"
 
+#if defined(MOZ_WIDGET_QT)
+#include <qwidget.h>
+#include <qapplication.h>
+#endif
+
 #ifdef XP_MACOSX
 #include "MacLaunchHelper.h"
 #include "MacApplicationDelegate.h"
 #endif
 
 #ifdef XP_OS2
 #include "private/pprthred.h"
 #endif
@@ -2793,16 +2798,19 @@ XRE_main(int argc, char* argv[], const n
 #define HAVE_DESKTOP_STARTUP_ID
     const char* desktopStartupIDEnv = PR_GetEnv("DESKTOP_STARTUP_ID");
     nsCAutoString desktopStartupID;
     if (desktopStartupIDEnv) {
       desktopStartupID.Assign(desktopStartupIDEnv);
     }
 #endif
 
+#if defined(MOZ_WIDGET_QT)
+    QApplication app(gArgc, gArgv);
+#endif
 #if defined(MOZ_WIDGET_GTK2)
 #ifdef MOZ_MEMORY
     // Disable the slice allocator, since jemalloc already uses similar layout
     // algorithms, and using a sub-allocator tends to increase fragmentation.
     // This must be done before g_thread_init() is called.
     g_slice_set_config(G_SLICE_CONFIG_ALWAYS_MALLOC, 1);
 #endif
     g_thread_init(NULL);
--- a/uriloader/exthandler/Makefile.in
+++ b/uriloader/exthandler/Makefile.in
@@ -108,16 +108,21 @@ endif
 
 LOCAL_INCLUDES = -I$(srcdir)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 OSHELPER	+= nsGNOMERegistry.cpp
 OSHELPER  += nsMIMEInfoUnix.cpp
 endif
 
+ifeq ($(MOZ_WIDGET_TOOLKIT),qt)
+OSHELPER += nsGNOMERegistry.cpp
+OSHELPER += nsMIMEInfoUnix.cpp
+endif
+
 ifeq ($(MOZ_WIDGET_TOOLKIT),beos)
 OSHELPER  += nsMIMEInfoBeOS.cpp
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 OSHELPER  += nsMIMEInfoWin.cpp
 LOCAL_INCLUDES += -I$(srcdir)/win
 endif
--- a/uriloader/exthandler/unix/nsGNOMERegistry.cpp
+++ b/uriloader/exthandler/unix/nsGNOMERegistry.cpp
@@ -42,18 +42,20 @@
 #include "nsString.h"
 #include "nsIComponentManager.h"
 #include "nsILocalFile.h"
 #include "nsMIMEInfoUnix.h"
 #include "nsAutoPtr.h"
 #include "nsIGConfService.h"
 #include "nsIGnomeVFSService.h"
 
+#ifdef MOZ_WIDGET_GTK2
 #include <glib.h>
 #include <glib-object.h>
+#endif
 
 /* static */ PRBool
 nsGNOMERegistry::HandlerExists(const char *aProtocolScheme)
 {
   nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
   if (!gconf)
     return PR_FALSE;
 
--- a/widget/public/Makefile.in
+++ b/widget/public/Makefile.in
@@ -69,17 +69,17 @@ endif
 ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
 EXPORTS		+= nsIDragSessionOS2.h
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),beos)
 EXPORTS		+= nsIDragSessionBeOS.h
 endif
 
-ifneq (,$(filter gtk2,$(MOZ_WIDGET_TOOLKIT)))
+ifneq (,$(filter qt gtk2,$(MOZ_WIDGET_TOOLKIT)))
 EXPORTS		+= \
 		nsIDragSessionGTK.h \
 		nsIPrintDialogService.h \
 		$(NULL)
 endif
 
 XPIDLSRCS	= \
 		nsIAppShell.idl \
--- a/widget/src/Makefile.in
+++ b/widget/src/Makefile.in
@@ -42,16 +42,18 @@ VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE  = widget
 
 PACKAGE_FILE = widget.pkg
 PACKAGE_VARS += \
 	MOZ_ENABLE_GTK2 \
+	MOZ_ENABLE_QT \
+	MOZ_ENABLE_XLIB \
 	MOZ_ENABLE_PHOTON \
 	MOZ_ENABLE_XREMOTE \
 	$(NULL)
 
 DIRS		= xpwidgets support
 
 ifneq (,$(filter beos os2 mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
 DIRS		+= $(MOZ_WIDGET_TOOLKIT)
@@ -70,14 +72,18 @@ endif
 #
 ifdef MOZ_ENABLE_GTK2
 DIRS		+= gtk2
 ifdef MOZ_X11
 DIRS		+= gtkxtbin
 endif
 endif
 
+ifeq (qt,$(MOZ_WIDGET_TOOLKIT))
+DIRS		+= qt
+endif
+
 ifdef MOZ_ENABLE_PHOTON
 DIRS		+= photon
 endif
 
 include $(topsrcdir)/config/rules.mk
 
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/Makefile.in
@@ -0,0 +1,149 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   John C. Griggs <johng@corel.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE		= widget
+LIBRARY_NAME	= widget_qt
+EXPORT_LIBRARY = 1
+IS_COMPONENT    = 1
+MODULE_NAME	= nsWidgetQtModule
+GRE_MODULE	= 1
+LIBXUL_LIBRARY	= 1
+
+REQUIRES	= xpcom \
+		  string \
+		  gfx \
+		  pref \
+		  dom \
+		  necko \
+		  uconv \
+		  intl \
+		  imglib2 \
+		  view \
+		  content \
+		  layout \
+		  util \
+		  locale \
+		  thebes \
+		  cairo \
+		  unicharutil \
+		  $(NULL)
+
+MOCSRCS = \
+		moc_mozqwidget.cpp \
+		moc_nsAppShell.cpp \
+		$(NULL)
+
+
+CSRCS = \
+		keysym2ucs.c \
+$(NULL)
+
+CPPSRCS	= \
+		$(MOCSRCS) \
+		nsAppShell.cpp \
+		nsWidgetFactory.cpp \
+		nsWindow.cpp \
+		nsLookAndFeel.cpp \
+		nsToolkit.cpp \
+		nsScreenQt.cpp \
+		nsScreenManagerQt.cpp \
+		nsQtKeyUtils.cpp \
+		nsClipboard.cpp \
+		nsBidiKeyboard.cpp \
+		nsIdleServiceQt.cpp \
+		nsDragService.cpp \
+		nsNativeThemeQt.cpp \
+		mozqwidget.cpp \
+		nsSound.cpp \
+		nsFilePicker.cpp \
+		$(NULL)
+
+SHARED_LIBRARY_LIBS = ../xpwidgets/libxpwidgets_s.a
+
+EXTRA_DSO_LDOPTS = \
+		$(MOZ_COMPONENT_LIBS) \
+		-lgkgfx \
+		-lthebes \
+		$(LCMS_LIBS) \
+		$(MOZ_JS_LIBS) \
+		$(MOZ_QT_LIBS) \
+		$(GLIB_LIBS) \
+		$(NULL)
+
+
+EXTRA_DSO_LDOPTS += -L$(DIST)/lib $(MOZ_XLIB_LDFLAGS) $(XLIBS)
+
+# If not primary toolkit, install in secondary path
+ifneq (qt,$(MOZ_WIDGET_TOOLKIT))
+INACTIVE_COMPONENT = 1
+endif
+
+include $(topsrcdir)/config/rules.mk
+
+CXXFLAGS	+= $(MOZ_QT_CFLAGS) $(GLIB_CFLAGS)
+CFLAGS		+= $(MOZ_QT_CFLAGS) $(GLIB_CFLAGS)
+
+DEFINES		+= -D_IMPL_NS_WIDGET
+#DEFINES		+= -DDEBUG_WIDGETS
+
+ifeq ($(OS_ARCH), Linux)
+DEFINES         += -D_BSD_SOURCE
+endif
+ifeq ($(OS_ARCH), SunOS) 
+ifndef GNU_CC
+# When using Sun's WorkShop compiler, including
+# /wherever/workshop-5.0/SC5.0/include/CC/std/time.h
+# causes most of these compiles to fail with:
+# line 29: Error: Multiple declaration for std::tm.
+# So, this gets around the problem.
+DEFINES         += -D_TIME_H=1
+endif
+endif
+
+LOCAL_INCLUDES	+= \
+		   -I$(topsrcdir)/widget/src/xpwidgets \
+		   -I$(srcdir) \
+		   $(NULL)
+
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/keysym2ucs.c
@@ -0,0 +1,899 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/*
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is from xterm-122 source XFree86: xc/programs/xterm/keysym2ucs.c,v 1.3 1999/07/11 08:49:37 dawes Exp.
+ *
+ * The Initial Developer of the Original Code is
+ * Markus G. Kuhn <mkuhn@acm.org> and Richard Verhoeven <river@win.tue.nl>.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Frank Tang <ftang@netscape.com> adopt into mozilla
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/*
+ * This module converts keysym values into the corresponding ISO 10646-1
+ * (UCS, Unicode) values.
+ *
+ * The array keysymtab[] contains pairs of X11 keysym values for graphical
+ * characters and the corresponding Unicode value. The function
+ * keysym2ucs() maps a keysym onto a Unicode value using a binary search,
+ * therefore keysymtab[] must remain SORTED by keysym value.
+ *
+ * The keysym -> UTF-8 conversion will hopefully one day be provided
+ * by Xlib via XmbLookupString() and should ideally not have to be
+ * done in X applications. But we are not there yet.
+ *
+ * We allow to represent any UCS character in the range U+00000000 to
+ * U+00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff.
+ * This admittedly does not cover the entire 31-bit space of UCS, but
+ * it does cover all of the characters up to U+10FFFF, which can be
+ * represented by UTF-16, and more, and it is very unlikely that higher
+ * UCS codes will ever be assigned by ISO. So to get Unicode character
+ * U+ABCD you can directly use keysym 0x1000abcd.
+ *
+ * NOTE: The comments in the table below contain the actual character
+ * encoded in UTF-8, so for viewing and editing best use an editor in
+ * UTF-8 mode.
+ *
+ * Author: Markus G. Kuhn <mkuhn@acm.org>, University of Cambridge, June 1999
+ *
+ * Special thanks to Richard Verhoeven <river@win.tue.nl> for preparing
+ * an initial draft of the mapping table.
+ *
+ * This software is in the public domain. Share and enjoy!
+ */
+
+#include "keysym2ucs.h"
+
+struct codepair {
+  unsigned short keysym;
+  unsigned short ucs;
+} keysymtab[] = {
+  { 0x01a1, 0x0104 }, /*                     Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK */
+  { 0x01a2, 0x02d8 }, /*                       breve ˘ BREVE */
+  { 0x01a3, 0x0141 }, /*                     Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE */
+  { 0x01a5, 0x013d }, /*                      Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON */
+  { 0x01a6, 0x015a }, /*                      Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE */
+  { 0x01a9, 0x0160 }, /*                      Scaron Š LATIN CAPITAL LETTER S WITH CARON */
+  { 0x01aa, 0x015e }, /*                    Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA */
+  { 0x01ab, 0x0164 }, /*                      Tcaron Ť LATIN CAPITAL LETTER T WITH CARON */
+  { 0x01ac, 0x0179 }, /*                      Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE */
+  { 0x01ae, 0x017d }, /*                      Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON */
+  { 0x01af, 0x017b }, /*                   Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE */
+  { 0x01b1, 0x0105 }, /*                     aogonek ą LATIN SMALL LETTER A WITH OGONEK */
+  { 0x01b2, 0x02db }, /*                      ogonek ˛ OGONEK */
+  { 0x01b3, 0x0142 }, /*                     lstroke ł LATIN SMALL LETTER L WITH STROKE */
+  { 0x01b5, 0x013e }, /*                      lcaron ľ LATIN SMALL LETTER L WITH CARON */
+  { 0x01b6, 0x015b }, /*                      sacute ś LATIN SMALL LETTER S WITH ACUTE */
+  { 0x01b7, 0x02c7 }, /*                       caron ˇ CARON */
+  { 0x01b9, 0x0161 }, /*                      scaron š LATIN SMALL LETTER S WITH CARON */
+  { 0x01ba, 0x015f }, /*                    scedilla ş LATIN SMALL LETTER S WITH CEDILLA */
+  { 0x01bb, 0x0165 }, /*                      tcaron ť LATIN SMALL LETTER T WITH CARON */
+  { 0x01bc, 0x017a }, /*                      zacute ź LATIN SMALL LETTER Z WITH ACUTE */
+  { 0x01bd, 0x02dd }, /*                 doubleacute ˝ DOUBLE ACUTE ACCENT */
+  { 0x01be, 0x017e }, /*                      zcaron ž LATIN SMALL LETTER Z WITH CARON */
+  { 0x01bf, 0x017c }, /*                   zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE */
+  { 0x01c0, 0x0154 }, /*                      Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE */
+  { 0x01c3, 0x0102 }, /*                      Abreve Ă LATIN CAPITAL LETTER A WITH BREVE */
+  { 0x01c5, 0x0139 }, /*                      Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE */
+  { 0x01c6, 0x0106 }, /*                      Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE */
+  { 0x01c8, 0x010c }, /*                      Ccaron Č LATIN CAPITAL LETTER C WITH CARON */
+  { 0x01ca, 0x0118 }, /*                     Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK */
+  { 0x01cc, 0x011a }, /*                      Ecaron Ě LATIN CAPITAL LETTER E WITH CARON */
+  { 0x01cf, 0x010e }, /*                      Dcaron Ď LATIN CAPITAL LETTER D WITH CARON */
+  { 0x01d0, 0x0110 }, /*                     Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE */
+  { 0x01d1, 0x0143 }, /*                      Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE */
+  { 0x01d2, 0x0147 }, /*                      Ncaron Ň LATIN CAPITAL LETTER N WITH CARON */
+  { 0x01d5, 0x0150 }, /*                Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */
+  { 0x01d8, 0x0158 }, /*                      Rcaron Ř LATIN CAPITAL LETTER R WITH CARON */
+  { 0x01d9, 0x016e }, /*                       Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE */
+  { 0x01db, 0x0170 }, /*                Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */
+  { 0x01de, 0x0162 }, /*                    Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA */
+  { 0x01e0, 0x0155 }, /*                      racute ŕ LATIN SMALL LETTER R WITH ACUTE */
+  { 0x01e3, 0x0103 }, /*                      abreve ă LATIN SMALL LETTER A WITH BREVE */
+  { 0x01e5, 0x013a }, /*                      lacute ĺ LATIN SMALL LETTER L WITH ACUTE */
+  { 0x01e6, 0x0107 }, /*                      cacute ć LATIN SMALL LETTER C WITH ACUTE */
+  { 0x01e8, 0x010d }, /*                      ccaron č LATIN SMALL LETTER C WITH CARON */
+  { 0x01ea, 0x0119 }, /*                     eogonek ę LATIN SMALL LETTER E WITH OGONEK */
+  { 0x01ec, 0x011b }, /*                      ecaron ě LATIN SMALL LETTER E WITH CARON */
+  { 0x01ef, 0x010f }, /*                      dcaron ď LATIN SMALL LETTER D WITH CARON */
+  { 0x01f0, 0x0111 }, /*                     dstroke đ LATIN SMALL LETTER D WITH STROKE */
+  { 0x01f1, 0x0144 }, /*                      nacute ń LATIN SMALL LETTER N WITH ACUTE */
+  { 0x01f2, 0x0148 }, /*                      ncaron ň LATIN SMALL LETTER N WITH CARON */
+  { 0x01f5, 0x0151 }, /*                odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE */
+  { 0x01f8, 0x0159 }, /*                      rcaron ř LATIN SMALL LETTER R WITH CARON */
+  { 0x01f9, 0x016f }, /*                       uring ů LATIN SMALL LETTER U WITH RING ABOVE */
+  { 0x01fb, 0x0171 }, /*                udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE */
+  { 0x01fe, 0x0163 }, /*                    tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA */
+  { 0x01ff, 0x02d9 }, /*                    abovedot ˙ DOT ABOVE */
+  { 0x02a1, 0x0126 }, /*                     Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE */
+  { 0x02a6, 0x0124 }, /*                 Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX */
+  { 0x02a9, 0x0130 }, /*                   Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE */
+  { 0x02ab, 0x011e }, /*                      Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE */
+  { 0x02ac, 0x0134 }, /*                 Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX */
+  { 0x02b1, 0x0127 }, /*                     hstroke ħ LATIN SMALL LETTER H WITH STROKE */
+  { 0x02b6, 0x0125 }, /*                 hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX */
+  { 0x02b9, 0x0131 }, /*                    idotless ı LATIN SMALL LETTER DOTLESS I */
+  { 0x02bb, 0x011f }, /*                      gbreve ğ LATIN SMALL LETTER G WITH BREVE */
+  { 0x02bc, 0x0135 }, /*                 jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX */
+  { 0x02c5, 0x010a }, /*                   Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE */
+  { 0x02c6, 0x0108 }, /*                 Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX */
+  { 0x02d5, 0x0120 }, /*                   Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE */
+  { 0x02d8, 0x011c }, /*                 Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX */
+  { 0x02dd, 0x016c }, /*                      Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE */
+  { 0x02de, 0x015c }, /*                 Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX */
+  { 0x02e5, 0x010b }, /*                   cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE */
+  { 0x02e6, 0x0109 }, /*                 ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX */
+  { 0x02f5, 0x0121 }, /*                   gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE */
+  { 0x02f8, 0x011d }, /*                 gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX */
+  { 0x02fd, 0x016d }, /*                      ubreve ŭ LATIN SMALL LETTER U WITH BREVE */
+  { 0x02fe, 0x015d }, /*                 scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX */
+  { 0x03a2, 0x0138 }, /*                         kra ĸ LATIN SMALL LETTER KRA */
+  { 0x03a3, 0x0156 }, /*                    Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA */
+  { 0x03a5, 0x0128 }, /*                      Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE */
+  { 0x03a6, 0x013b }, /*                    Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA */
+  { 0x03aa, 0x0112 }, /*                     Emacron Ē LATIN CAPITAL LETTER E WITH MACRON */
+  { 0x03ab, 0x0122 }, /*                    Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA */
+  { 0x03ac, 0x0166 }, /*                      Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE */
+  { 0x03b3, 0x0157 }, /*                    rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA */
+  { 0x03b5, 0x0129 }, /*                      itilde ĩ LATIN SMALL LETTER I WITH TILDE */
+  { 0x03b6, 0x013c }, /*                    lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA */
+  { 0x03ba, 0x0113 }, /*                     emacron ē LATIN SMALL LETTER E WITH MACRON */
+  { 0x03bb, 0x0123 }, /*                    gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA */
+  { 0x03bc, 0x0167 }, /*                      tslash ŧ LATIN SMALL LETTER T WITH STROKE */
+  { 0x03bd, 0x014a }, /*                         ENG Ŋ LATIN CAPITAL LETTER ENG */
+  { 0x03bf, 0x014b }, /*                         eng ŋ LATIN SMALL LETTER ENG */
+  { 0x03c0, 0x0100 }, /*                     Amacron Ā LATIN CAPITAL LETTER A WITH MACRON */
+  { 0x03c7, 0x012e }, /*                     Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK */
+  { 0x03cc, 0x0116 }, /*                   Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE */
+  { 0x03cf, 0x012a }, /*                     Imacron Ī LATIN CAPITAL LETTER I WITH MACRON */
+  { 0x03d1, 0x0145 }, /*                    Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA */
+  { 0x03d2, 0x014c }, /*                     Omacron Ō LATIN CAPITAL LETTER O WITH MACRON */
+  { 0x03d3, 0x0136 }, /*                    Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA */
+  { 0x03d9, 0x0172 }, /*                     Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK */
+  { 0x03dd, 0x0168 }, /*                      Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE */
+  { 0x03de, 0x016a }, /*                     Umacron Ū LATIN CAPITAL LETTER U WITH MACRON */
+  { 0x03e0, 0x0101 }, /*                     amacron ā LATIN SMALL LETTER A WITH MACRON */
+  { 0x03e7, 0x012f }, /*                     iogonek į LATIN SMALL LETTER I WITH OGONEK */
+  { 0x03ec, 0x0117 }, /*                   eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE */
+  { 0x03ef, 0x012b }, /*                     imacron ī LATIN SMALL LETTER I WITH MACRON */
+  { 0x03f1, 0x0146 }, /*                    ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA */
+  { 0x03f2, 0x014d }, /*                     omacron ō LATIN SMALL LETTER O WITH MACRON */
+  { 0x03f3, 0x0137 }, /*                    kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA */
+  { 0x03f9, 0x0173 }, /*                     uogonek ų LATIN SMALL LETTER U WITH OGONEK */
+  { 0x03fd, 0x0169 }, /*                      utilde ũ LATIN SMALL LETTER U WITH TILDE */
+  { 0x03fe, 0x016b }, /*                     umacron ū LATIN SMALL LETTER U WITH MACRON */
+  { 0x047e, 0x203e }, /*                    overline ‾ OVERLINE */
+  { 0x04a1, 0x3002 }, /*               kana_fullstop 。 IDEOGRAPHIC FULL STOP */
+  { 0x04a2, 0x300c }, /*         kana_openingbracket 「 LEFT CORNER BRACKET */
+  { 0x04a3, 0x300d }, /*         kana_closingbracket 」 RIGHT CORNER BRACKET */
+  { 0x04a4, 0x3001 }, /*                  kana_comma 、 IDEOGRAPHIC COMMA */
+  { 0x04a5, 0x30fb }, /*            kana_conjunctive ・ KATAKANA MIDDLE DOT */
+  { 0x04a6, 0x30f2 }, /*                     kana_WO ヲ KATAKANA LETTER WO */
+  { 0x04a7, 0x30a1 }, /*                      kana_a ァ KATAKANA LETTER SMALL A */
+  { 0x04a8, 0x30a3 }, /*                      kana_i ィ KATAKANA LETTER SMALL I */
+  { 0x04a9, 0x30a5 }, /*                      kana_u ゥ KATAKANA LETTER SMALL U */
+  { 0x04aa, 0x30a7 }, /*                      kana_e ェ KATAKANA LETTER SMALL E */
+  { 0x04ab, 0x30a9 }, /*                      kana_o ォ KATAKANA LETTER SMALL O */
+  { 0x04ac, 0x30e3 }, /*                     kana_ya ャ KATAKANA LETTER SMALL YA */
+  { 0x04ad, 0x30e5 }, /*                     kana_yu ュ KATAKANA LETTER SMALL YU */
+  { 0x04ae, 0x30e7 }, /*                     kana_yo ョ KATAKANA LETTER SMALL YO */
+  { 0x04af, 0x30c3 }, /*                    kana_tsu ッ KATAKANA LETTER SMALL TU */
+  { 0x04b0, 0x30fc }, /*              prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK */
+  { 0x04b1, 0x30a2 }, /*                      kana_A ア KATAKANA LETTER A */
+  { 0x04b2, 0x30a4 }, /*                      kana_I イ KATAKANA LETTER I */
+  { 0x04b3, 0x30a6 }, /*                      kana_U ウ KATAKANA LETTER U */
+  { 0x04b4, 0x30a8 }, /*                      kana_E エ KATAKANA LETTER E */
+  { 0x04b5, 0x30aa }, /*                      kana_O オ KATAKANA LETTER O */
+  { 0x04b6, 0x30ab }, /*                     kana_KA カ KATAKANA LETTER KA */
+  { 0x04b7, 0x30ad }, /*                     kana_KI キ KATAKANA LETTER KI */
+  { 0x04b8, 0x30af }, /*                     kana_KU ク KATAKANA LETTER KU */
+  { 0x04b9, 0x30b1 }, /*                     kana_KE ケ KATAKANA LETTER KE */
+  { 0x04ba, 0x30b3 }, /*                     kana_KO コ KATAKANA LETTER KO */
+  { 0x04bb, 0x30b5 }, /*                     kana_SA サ KATAKANA LETTER SA */
+  { 0x04bc, 0x30b7 }, /*                    kana_SHI シ KATAKANA LETTER SI */
+  { 0x04bd, 0x30b9 }, /*                     kana_SU ス KATAKANA LETTER SU */
+  { 0x04be, 0x30bb }, /*                     kana_SE セ KATAKANA LETTER SE */
+  { 0x04bf, 0x30bd }, /*                     kana_SO ソ KATAKANA LETTER SO */
+  { 0x04c0, 0x30bf }, /*                     kana_TA タ KATAKANA LETTER TA */
+  { 0x04c1, 0x30c1 }, /*                    kana_CHI チ KATAKANA LETTER TI */
+  { 0x04c2, 0x30c4 }, /*                    kana_TSU ツ KATAKANA LETTER TU */
+  { 0x04c3, 0x30c6 }, /*                     kana_TE テ KATAKANA LETTER TE */
+  { 0x04c4, 0x30c8 }, /*                     kana_TO ト KATAKANA LETTER TO */
+  { 0x04c5, 0x30ca }, /*                     kana_NA ナ KATAKANA LETTER NA */
+  { 0x04c6, 0x30cb }, /*                     kana_NI ニ KATAKANA LETTER NI */
+  { 0x04c7, 0x30cc }, /*                     kana_NU ヌ KATAKANA LETTER NU */
+  { 0x04c8, 0x30cd }, /*                     kana_NE ネ KATAKANA LETTER NE */
+  { 0x04c9, 0x30ce }, /*                     kana_NO ノ KATAKANA LETTER NO */
+  { 0x04ca, 0x30cf }, /*                     kana_HA ハ KATAKANA LETTER HA */
+  { 0x04cb, 0x30d2 }, /*                     kana_HI ヒ KATAKANA LETTER HI */
+  { 0x04cc, 0x30d5 }, /*                     kana_FU フ KATAKANA LETTER HU */
+  { 0x04cd, 0x30d8 }, /*                     kana_HE ヘ KATAKANA LETTER HE */
+  { 0x04ce, 0x30db }, /*                     kana_HO ホ KATAKANA LETTER HO */
+  { 0x04cf, 0x30de }, /*                     kana_MA マ KATAKANA LETTER MA */
+  { 0x04d0, 0x30df }, /*                     kana_MI ミ KATAKANA LETTER MI */
+  { 0x04d1, 0x30e0 }, /*                     kana_MU ム KATAKANA LETTER MU */
+  { 0x04d2, 0x30e1 }, /*                     kana_ME メ KATAKANA LETTER ME */
+  { 0x04d3, 0x30e2 }, /*                     kana_MO モ KATAKANA LETTER MO */
+  { 0x04d4, 0x30e4 }, /*                     kana_YA ヤ KATAKANA LETTER YA */
+  { 0x04d5, 0x30e6 }, /*                     kana_YU ユ KATAKANA LETTER YU */
+  { 0x04d6, 0x30e8 }, /*                     kana_YO ヨ KATAKANA LETTER YO */
+  { 0x04d7, 0x30e9 }, /*                     kana_RA ラ KATAKANA LETTER RA */
+  { 0x04d8, 0x30ea }, /*                     kana_RI リ KATAKANA LETTER RI */
+  { 0x04d9, 0x30eb }, /*                     kana_RU ル KATAKANA LETTER RU */
+  { 0x04da, 0x30ec }, /*                     kana_RE レ KATAKANA LETTER RE */
+  { 0x04db, 0x30ed }, /*                     kana_RO ロ KATAKANA LETTER RO */
+  { 0x04dc, 0x30ef }, /*                     kana_WA ワ KATAKANA LETTER WA */
+  { 0x04dd, 0x30f3 }, /*                      kana_N ン KATAKANA LETTER N */
+  { 0x04de, 0x309b }, /*                 voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK */
+  { 0x04df, 0x309c }, /*             semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */
+  { 0x05ac, 0x060c }, /*                Arabic_comma ، ARABIC COMMA */
+  { 0x05bb, 0x061b }, /*            Arabic_semicolon ؛ ARABIC SEMICOLON */
+  { 0x05bf, 0x061f }, /*        Arabic_question_mark ؟ ARABIC QUESTION MARK */
+  { 0x05c1, 0x0621 }, /*                Arabic_hamza ء ARABIC LETTER HAMZA */
+  { 0x05c2, 0x0622 }, /*          Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE */
+  { 0x05c3, 0x0623 }, /*          Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE */
+  { 0x05c4, 0x0624 }, /*           Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE */
+  { 0x05c5, 0x0625 }, /*       Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW */
+  { 0x05c6, 0x0626 }, /*           Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE */
+  { 0x05c7, 0x0627 }, /*                 Arabic_alef ا ARABIC LETTER ALEF */
+  { 0x05c8, 0x0628 }, /*                  Arabic_beh ب ARABIC LETTER BEH */
+  { 0x05c9, 0x0629 }, /*           Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA */
+  { 0x05ca, 0x062a }, /*                  Arabic_teh ت ARABIC LETTER TEH */
+  { 0x05cb, 0x062b }, /*                 Arabic_theh ث ARABIC LETTER THEH */
+  { 0x05cc, 0x062c }, /*                 Arabic_jeem ج ARABIC LETTER JEEM */
+  { 0x05cd, 0x062d }, /*                  Arabic_hah ح ARABIC LETTER HAH */
+  { 0x05ce, 0x062e }, /*                 Arabic_khah خ ARABIC LETTER KHAH */
+  { 0x05cf, 0x062f }, /*                  Arabic_dal د ARABIC LETTER DAL */
+  { 0x05d0, 0x0630 }, /*                 Arabic_thal ذ ARABIC LETTER THAL */
+  { 0x05d1, 0x0631 }, /*                   Arabic_ra ر ARABIC LETTER REH */
+  { 0x05d2, 0x0632 }, /*                 Arabic_zain ز ARABIC LETTER ZAIN */
+  { 0x05d3, 0x0633 }, /*                 Arabic_seen س ARABIC LETTER SEEN */
+  { 0x05d4, 0x0634 }, /*                Arabic_sheen ش ARABIC LETTER SHEEN */
+  { 0x05d5, 0x0635 }, /*                  Arabic_sad ص ARABIC LETTER SAD */
+  { 0x05d6, 0x0636 }, /*                  Arabic_dad ض ARABIC LETTER DAD */
+  { 0x05d7, 0x0637 }, /*                  Arabic_tah ط ARABIC LETTER TAH */
+  { 0x05d8, 0x0638 }, /*                  Arabic_zah ظ ARABIC LETTER ZAH */
+  { 0x05d9, 0x0639 }, /*                  Arabic_ain ع ARABIC LETTER AIN */
+  { 0x05da, 0x063a }, /*                Arabic_ghain غ ARABIC LETTER GHAIN */
+  { 0x05e0, 0x0640 }, /*              Arabic_tatweel ـ ARABIC TATWEEL */
+  { 0x05e1, 0x0641 }, /*                  Arabic_feh ف ARABIC LETTER FEH */
+  { 0x05e2, 0x0642 }, /*                  Arabic_qaf ق ARABIC LETTER QAF */
+  { 0x05e3, 0x0643 }, /*                  Arabic_kaf ك ARABIC LETTER KAF */
+  { 0x05e4, 0x0644 }, /*                  Arabic_lam ل ARABIC LETTER LAM */
+  { 0x05e5, 0x0645 }, /*                 Arabic_meem م ARABIC LETTER MEEM */
+  { 0x05e6, 0x0646 }, /*                 Arabic_noon ن ARABIC LETTER NOON */
+  { 0x05e7, 0x0647 }, /*                   Arabic_ha ه ARABIC LETTER HEH */
+  { 0x05e8, 0x0648 }, /*                  Arabic_waw و ARABIC LETTER WAW */
+  { 0x05e9, 0x0649 }, /*          Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA */
+  { 0x05ea, 0x064a }, /*                  Arabic_yeh ي ARABIC LETTER YEH */
+  { 0x05eb, 0x064b }, /*             Arabic_fathatan ً ARABIC FATHATAN */
+  { 0x05ec, 0x064c }, /*             Arabic_dammatan ٌ ARABIC DAMMATAN */
+  { 0x05ed, 0x064d }, /*             Arabic_kasratan ٍ ARABIC KASRATAN */
+  { 0x05ee, 0x064e }, /*                Arabic_fatha َ ARABIC FATHA */
+  { 0x05ef, 0x064f }, /*                Arabic_damma ُ ARABIC DAMMA */
+  { 0x05f0, 0x0650 }, /*                Arabic_kasra ِ ARABIC KASRA */
+  { 0x05f1, 0x0651 }, /*               Arabic_shadda ّ ARABIC SHADDA */
+  { 0x05f2, 0x0652 }, /*                Arabic_sukun ْ ARABIC SUKUN */
+  { 0x06a1, 0x0452 }, /*                 Serbian_dje ђ CYRILLIC SMALL LETTER DJE */
+  { 0x06a2, 0x0453 }, /*               Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE */
+  { 0x06a3, 0x0451 }, /*                 Cyrillic_io ё CYRILLIC SMALL LETTER IO */
+  { 0x06a4, 0x0454 }, /*                Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE */
+  { 0x06a5, 0x0455 }, /*               Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE */
+  { 0x06a6, 0x0456 }, /*                 Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */
+  { 0x06a7, 0x0457 }, /*                Ukrainian_yi ї CYRILLIC SMALL LETTER YI */
+  { 0x06a8, 0x0458 }, /*                 Cyrillic_je ј CYRILLIC SMALL LETTER JE */
+  { 0x06a9, 0x0459 }, /*                Cyrillic_lje љ CYRILLIC SMALL LETTER LJE */
+  { 0x06aa, 0x045a }, /*                Cyrillic_nje њ CYRILLIC SMALL LETTER NJE */
+  { 0x06ab, 0x045b }, /*                Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE */
+  { 0x06ac, 0x045c }, /*               Macedonia_kje ќ CYRILLIC SMALL LETTER KJE */
+  { 0x06ad, 0x0491 }, /*   Ukrainian_ghe_with_upturn ґ CYRILLIC SMALL LETTER GHE WITH UPTURN */
+  { 0x06ae, 0x045e }, /*         Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U */
+  { 0x06af, 0x045f }, /*               Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE */
+  { 0x06b0, 0x2116 }, /*                  numerosign № NUMERO SIGN */
+  { 0x06b1, 0x0402 }, /*                 Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE */
+  { 0x06b2, 0x0403 }, /*               Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE */
+  { 0x06b3, 0x0401 }, /*                 Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO */
+  { 0x06b4, 0x0404 }, /*                Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE */
+  { 0x06b5, 0x0405 }, /*               Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE */
+  { 0x06b6, 0x0406 }, /*                 Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */
+  { 0x06b7, 0x0407 }, /*                Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI */
+  { 0x06b8, 0x0408 }, /*                 Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE */
+  { 0x06b9, 0x0409 }, /*                Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE */
+  { 0x06ba, 0x040a }, /*                Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE */
+  { 0x06bb, 0x040b }, /*                Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE */
+  { 0x06bc, 0x040c }, /*               Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE */
+  { 0x06bd, 0x0490 }, /*   Ukrainian_GHE_WITH_UPTURN Ґ CYRILLIC CAPITAL LETTER GHE WITH UPTURN */
+  { 0x06be, 0x040e }, /*         Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U */
+  { 0x06bf, 0x040f }, /*               Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE */
+  { 0x06c0, 0x044e }, /*                 Cyrillic_yu ю CYRILLIC SMALL LETTER YU */
+  { 0x06c1, 0x0430 }, /*                  Cyrillic_a а CYRILLIC SMALL LETTER A */
+  { 0x06c2, 0x0431 }, /*                 Cyrillic_be б CYRILLIC SMALL LETTER BE */
+  { 0x06c3, 0x0446 }, /*                Cyrillic_tse ц CYRILLIC SMALL LETTER TSE */
+  { 0x06c4, 0x0434 }, /*                 Cyrillic_de д CYRILLIC SMALL LETTER DE */
+  { 0x06c5, 0x0435 }, /*                 Cyrillic_ie е CYRILLIC SMALL LETTER IE */
+  { 0x06c6, 0x0444 }, /*                 Cyrillic_ef ф CYRILLIC SMALL LETTER EF */
+  { 0x06c7, 0x0433 }, /*                Cyrillic_ghe г CYRILLIC SMALL LETTER GHE */
+  { 0x06c8, 0x0445 }, /*                 Cyrillic_ha х CYRILLIC SMALL LETTER HA */
+  { 0x06c9, 0x0438 }, /*                  Cyrillic_i и CYRILLIC SMALL LETTER I */
+  { 0x06ca, 0x0439 }, /*             Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I */
+  { 0x06cb, 0x043a }, /*                 Cyrillic_ka к CYRILLIC SMALL LETTER KA */
+  { 0x06cc, 0x043b }, /*                 Cyrillic_el л CYRILLIC SMALL LETTER EL */
+  { 0x06cd, 0x043c }, /*                 Cyrillic_em м CYRILLIC SMALL LETTER EM */
+  { 0x06ce, 0x043d }, /*                 Cyrillic_en н CYRILLIC SMALL LETTER EN */
+  { 0x06cf, 0x043e }, /*                  Cyrillic_o о CYRILLIC SMALL LETTER O */
+  { 0x06d0, 0x043f }, /*                 Cyrillic_pe п CYRILLIC SMALL LETTER PE */
+  { 0x06d1, 0x044f }, /*                 Cyrillic_ya я CYRILLIC SMALL LETTER YA */
+  { 0x06d2, 0x0440 }, /*                 Cyrillic_er р CYRILLIC SMALL LETTER ER */
+  { 0x06d3, 0x0441 }, /*                 Cyrillic_es с CYRILLIC SMALL LETTER ES */
+  { 0x06d4, 0x0442 }, /*                 Cyrillic_te т CYRILLIC SMALL LETTER TE */
+  { 0x06d5, 0x0443 }, /*                  Cyrillic_u у CYRILLIC SMALL LETTER U */
+  { 0x06d6, 0x0436 }, /*                Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE */
+  { 0x06d7, 0x0432 }, /*                 Cyrillic_ve в CYRILLIC SMALL LETTER VE */
+  { 0x06d8, 0x044c }, /*           Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN */
+  { 0x06d9, 0x044b }, /*               Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU */
+  { 0x06da, 0x0437 }, /*                 Cyrillic_ze з CYRILLIC SMALL LETTER ZE */
+  { 0x06db, 0x0448 }, /*                Cyrillic_sha ш CYRILLIC SMALL LETTER SHA */
+  { 0x06dc, 0x044d }, /*                  Cyrillic_e э CYRILLIC SMALL LETTER E */
+  { 0x06dd, 0x0449 }, /*              Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA */
+  { 0x06de, 0x0447 }, /*                Cyrillic_che ч CYRILLIC SMALL LETTER CHE */
+  { 0x06df, 0x044a }, /*           Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN */
+  { 0x06e0, 0x042e }, /*                 Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU */
+  { 0x06e1, 0x0410 }, /*                  Cyrillic_A А CYRILLIC CAPITAL LETTER A */
+  { 0x06e2, 0x0411 }, /*                 Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE */
+  { 0x06e3, 0x0426 }, /*                Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE */
+  { 0x06e4, 0x0414 }, /*                 Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE */
+  { 0x06e5, 0x0415 }, /*                 Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE */
+  { 0x06e6, 0x0424 }, /*                 Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF */
+  { 0x06e7, 0x0413 }, /*                Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE */
+  { 0x06e8, 0x0425 }, /*                 Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA */
+  { 0x06e9, 0x0418 }, /*                  Cyrillic_I И CYRILLIC CAPITAL LETTER I */
+  { 0x06ea, 0x0419 }, /*             Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I */
+  { 0x06eb, 0x041a }, /*                 Cyrillic_KA К CYRILLIC CAPITAL LETTER KA */
+  { 0x06ec, 0x041b }, /*                 Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL */
+  { 0x06ed, 0x041c }, /*                 Cyrillic_EM М CYRILLIC CAPITAL LETTER EM */
+  { 0x06ee, 0x041d }, /*                 Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN */
+  { 0x06ef, 0x041e }, /*                  Cyrillic_O О CYRILLIC CAPITAL LETTER O */
+  { 0x06f0, 0x041f }, /*                 Cyrillic_PE П CYRILLIC CAPITAL LETTER PE */
+  { 0x06f1, 0x042f }, /*                 Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA */
+  { 0x06f2, 0x0420 }, /*                 Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER */
+  { 0x06f3, 0x0421 }, /*                 Cyrillic_ES С CYRILLIC CAPITAL LETTER ES */
+  { 0x06f4, 0x0422 }, /*                 Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE */
+  { 0x06f5, 0x0423 }, /*                  Cyrillic_U У CYRILLIC CAPITAL LETTER U */
+  { 0x06f6, 0x0416 }, /*                Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE */
+  { 0x06f7, 0x0412 }, /*                 Cyrillic_VE В CYRILLIC CAPITAL LETTER VE */
+  { 0x06f8, 0x042c }, /*           Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN */
+  { 0x06f9, 0x042b }, /*               Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU */
+  { 0x06fa, 0x0417 }, /*                 Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE */
+  { 0x06fb, 0x0428 }, /*                Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA */
+  { 0x06fc, 0x042d }, /*                  Cyrillic_E Э CYRILLIC CAPITAL LETTER E */
+  { 0x06fd, 0x0429 }, /*              Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA */
+  { 0x06fe, 0x0427 }, /*                Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE */
+  { 0x06ff, 0x042a }, /*           Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN */
+  { 0x07a1, 0x0386 }, /*           Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS */
+  { 0x07a2, 0x0388 }, /*         Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */
+  { 0x07a3, 0x0389 }, /*             Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */
+  { 0x07a4, 0x038a }, /*            Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */
+  { 0x07a5, 0x03aa }, /*         Greek_IOTAdiaeresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */
+  { 0x07a7, 0x038c }, /*         Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */
+  { 0x07a8, 0x038e }, /*         Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */
+  { 0x07a9, 0x03ab }, /*       Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */
+  { 0x07ab, 0x038f }, /*           Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS */
+  { 0x07ae, 0x0385 }, /*        Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS */
+  { 0x07af, 0x2015 }, /*              Greek_horizbar ― HORIZONTAL BAR */
+  { 0x07b1, 0x03ac }, /*           Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */
+  { 0x07b2, 0x03ad }, /*         Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */
+  { 0x07b3, 0x03ae }, /*             Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS */
+  { 0x07b4, 0x03af }, /*            Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS */
+  { 0x07b5, 0x03ca }, /*          Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA */
+  { 0x07b6, 0x0390 }, /*    Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */
+  { 0x07b7, 0x03cc }, /*         Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS */
+  { 0x07b8, 0x03cd }, /*         Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS */
+  { 0x07b9, 0x03cb }, /*       Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA */
+  { 0x07ba, 0x03b0 }, /* Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */
+  { 0x07bb, 0x03ce }, /*           Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS */
+  { 0x07c1, 0x0391 }, /*                 Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA */
+  { 0x07c2, 0x0392 }, /*                  Greek_BETA Β GREEK CAPITAL LETTER BETA */
+  { 0x07c3, 0x0393 }, /*                 Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA */
+  { 0x07c4, 0x0394 }, /*                 Greek_DELTA Δ GREEK CAPITAL LETTER DELTA */
+  { 0x07c5, 0x0395 }, /*               Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON */
+  { 0x07c6, 0x0396 }, /*                  Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA */
+  { 0x07c7, 0x0397 }, /*                   Greek_ETA Η GREEK CAPITAL LETTER ETA */
+  { 0x07c8, 0x0398 }, /*                 Greek_THETA Θ GREEK CAPITAL LETTER THETA */
+  { 0x07c9, 0x0399 }, /*                  Greek_IOTA Ι GREEK CAPITAL LETTER IOTA */
+  { 0x07ca, 0x039a }, /*                 Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA */
+  { 0x07cb, 0x039b }, /*                Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA */
+  { 0x07cc, 0x039c }, /*                    Greek_MU Μ GREEK CAPITAL LETTER MU */
+  { 0x07cd, 0x039d }, /*                    Greek_NU Ν GREEK CAPITAL LETTER NU */
+  { 0x07ce, 0x039e }, /*                    Greek_XI Ξ GREEK CAPITAL LETTER XI */
+  { 0x07cf, 0x039f }, /*               Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON */
+  { 0x07d0, 0x03a0 }, /*                    Greek_PI Π GREEK CAPITAL LETTER PI */
+  { 0x07d1, 0x03a1 }, /*                   Greek_RHO Ρ GREEK CAPITAL LETTER RHO */
+  { 0x07d2, 0x03a3 }, /*                 Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA */
+  { 0x07d4, 0x03a4 }, /*                   Greek_TAU Τ GREEK CAPITAL LETTER TAU */
+  { 0x07d5, 0x03a5 }, /*               Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON */
+  { 0x07d6, 0x03a6 }, /*                   Greek_PHI Φ GREEK CAPITAL LETTER PHI */
+  { 0x07d7, 0x03a7 }, /*                   Greek_CHI Χ GREEK CAPITAL LETTER CHI */
+  { 0x07d8, 0x03a8 }, /*                   Greek_PSI Ψ GREEK CAPITAL LETTER PSI */
+  { 0x07d9, 0x03a9 }, /*                 Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */
+  { 0x07e1, 0x03b1 }, /*                 Greek_alpha α GREEK SMALL LETTER ALPHA */
+  { 0x07e2, 0x03b2 }, /*                  Greek_beta β GREEK SMALL LETTER BETA */
+  { 0x07e3, 0x03b3 }, /*                 Greek_gamma γ GREEK SMALL LETTER GAMMA */
+  { 0x07e4, 0x03b4 }, /*                 Greek_delta δ GREEK SMALL LETTER DELTA */
+  { 0x07e5, 0x03b5 }, /*               Greek_epsilon ε GREEK SMALL LETTER EPSILON */
+  { 0x07e6, 0x03b6 }, /*                  Greek_zeta ζ GREEK SMALL LETTER ZETA */
+  { 0x07e7, 0x03b7 }, /*                   Greek_eta η GREEK SMALL LETTER ETA */
+  { 0x07e8, 0x03b8 }, /*                 Greek_theta θ GREEK SMALL LETTER THETA */
+  { 0x07e9, 0x03b9 }, /*                  Greek_iota ι GREEK SMALL LETTER IOTA */
+  { 0x07ea, 0x03ba }, /*                 Greek_kappa κ GREEK SMALL LETTER KAPPA */
+  { 0x07eb, 0x03bb }, /*                Greek_lambda λ GREEK SMALL LETTER LAMDA */
+  { 0x07ec, 0x03bc }, /*                    Greek_mu μ GREEK SMALL LETTER MU */
+  { 0x07ed, 0x03bd }, /*                    Greek_nu ν GREEK SMALL LETTER NU */
+  { 0x07ee, 0x03be }, /*                    Greek_xi ξ GREEK SMALL LETTER XI */
+  { 0x07ef, 0x03bf }, /*               Greek_omicron ο GREEK SMALL LETTER OMICRON */
+  { 0x07f0, 0x03c0 }, /*                    Greek_pi π GREEK SMALL LETTER PI */
+  { 0x07f1, 0x03c1 }, /*                   Greek_rho ρ GREEK SMALL LETTER RHO */
+  { 0x07f2, 0x03c3 }, /*                 Greek_sigma σ GREEK SMALL LETTER SIGMA */
+  { 0x07f3, 0x03c2 }, /*       Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA */
+  { 0x07f4, 0x03c4 }, /*                   Greek_tau τ GREEK SMALL LETTER TAU */
+  { 0x07f5, 0x03c5 }, /*               Greek_upsilon υ GREEK SMALL LETTER UPSILON */
+  { 0x07f6, 0x03c6 }, /*                   Greek_phi φ GREEK SMALL LETTER PHI */
+  { 0x07f7, 0x03c7 }, /*                   Greek_chi χ GREEK SMALL LETTER CHI */
+  { 0x07f8, 0x03c8 }, /*                   Greek_psi ψ GREEK SMALL LETTER PSI */
+  { 0x07f9, 0x03c9 }, /*                 Greek_omega ω GREEK SMALL LETTER OMEGA */
+/*  0x08a1                               leftradical ? ??? */
+/*  0x08a2                            topleftradical ? ??? */
+/*  0x08a3                            horizconnector ? ??? */
+  { 0x08a4, 0x2320 }, /*                 topintegral ⌠ TOP HALF INTEGRAL */
+  { 0x08a5, 0x2321 }, /*                 botintegral ⌡ BOTTOM HALF INTEGRAL */
+  { 0x08a6, 0x2502 }, /*               vertconnector │ BOX DRAWINGS LIGHT VERTICAL */
+/*  0x08a7                          topleftsqbracket ? ??? */
+/*  0x08a8                          botleftsqbracket ? ??? */
+/*  0x08a9                         toprightsqbracket ? ??? */
+/*  0x08aa                         botrightsqbracket ? ??? */
+/*  0x08ab                             topleftparens ? ??? */
+/*  0x08ac                             botleftparens ? ??? */
+/*  0x08ad                            toprightparens ? ??? */
+/*  0x08ae                            botrightparens ? ??? */
+/*  0x08af                      leftmiddlecurlybrace ? ??? */
+/*  0x08b0                     rightmiddlecurlybrace ? ??? */
+/*  0x08b1                          topleftsummation ? ??? */
+/*  0x08b2                          botleftsummation ? ??? */
+/*  0x08b3                 topvertsummationconnector ? ??? */
+/*  0x08b4                 botvertsummationconnector ? ??? */
+/*  0x08b5                         toprightsummation ? ??? */
+/*  0x08b6                         botrightsummation ? ??? */
+/*  0x08b7                      rightmiddlesummation ? ??? */
+  { 0x08bc, 0x2264 }, /*               lessthanequal ≤ LESS-THAN OR EQUAL TO */
+  { 0x08bd, 0x2260 }, /*                    notequal ≠ NOT EQUAL TO */
+  { 0x08be, 0x2265 }, /*            greaterthanequal ≥ GREATER-THAN OR EQUAL TO */
+  { 0x08bf, 0x222b }, /*                    integral ∫ INTEGRAL */
+  { 0x08c0, 0x2234 }, /*                   therefore ∴ THEREFORE */
+  { 0x08c1, 0x221d }, /*                   variation ∝ PROPORTIONAL TO */
+  { 0x08c2, 0x221e }, /*                    infinity ∞ INFINITY */
+  { 0x08c5, 0x2207 }, /*                       nabla ∇ NABLA */
+  { 0x08c8, 0x2245 }, /*                 approximate ≅ APPROXIMATELY EQUAL TO */
+/*  0x08c9                              similarequal ? ??? */
+  { 0x08cd, 0x21d4 }, /*                    ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */
+  { 0x08ce, 0x21d2 }, /*                     implies ⇒ RIGHTWARDS DOUBLE ARROW */
+  { 0x08cf, 0x2261 }, /*                   identical ≡ IDENTICAL TO */
+  { 0x08d6, 0x221a }, /*                     radical √ SQUARE ROOT */
+  { 0x08da, 0x2282 }, /*                  includedin ⊂ SUBSET OF */
+  { 0x08db, 0x2283 }, /*                    includes ⊃ SUPERSET OF */
+  { 0x08dc, 0x2229 }, /*                intersection ∩ INTERSECTION */
+  { 0x08dd, 0x222a }, /*                       union ∪ UNION */
+  { 0x08de, 0x2227 }, /*                  logicaland ∧ LOGICAL AND */
+  { 0x08df, 0x2228 }, /*                   logicalor ∨ LOGICAL OR */
+  { 0x08ef, 0x2202 }, /*           partialderivative ∂ PARTIAL DIFFERENTIAL */
+  { 0x08f6, 0x0192 }, /*                    function ƒ LATIN SMALL LETTER F WITH HOOK */
+  { 0x08fb, 0x2190 }, /*                   leftarrow ← LEFTWARDS ARROW */
+  { 0x08fc, 0x2191 }, /*                     uparrow ↑ UPWARDS ARROW */
+  { 0x08fd, 0x2192 }, /*                  rightarrow → RIGHTWARDS ARROW */
+  { 0x08fe, 0x2193 }, /*                   downarrow ↓ DOWNWARDS ARROW */
+  { 0x09df, 0x2422 }, /*                       blank ␢ BLANK SYMBOL */
+  { 0x09e0, 0x25c6 }, /*                soliddiamond ◆ BLACK DIAMOND */
+  { 0x09e1, 0x2592 }, /*                checkerboard ▒ MEDIUM SHADE */
+  { 0x09e2, 0x2409 }, /*                          ht ␉ SYMBOL FOR HORIZONTAL TABULATION */
+  { 0x09e3, 0x240c }, /*                          ff ␌ SYMBOL FOR FORM FEED */
+  { 0x09e4, 0x240d }, /*                          cr ␍ SYMBOL FOR CARRIAGE RETURN */
+  { 0x09e5, 0x240a }, /*                          lf ␊ SYMBOL FOR LINE FEED */
+  { 0x09e8, 0x2424 }, /*                          nl ␤ SYMBOL FOR NEWLINE */
+  { 0x09e9, 0x240b }, /*                          vt ␋ SYMBOL FOR VERTICAL TABULATION */
+  { 0x09ea, 0x2518 }, /*              lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT */
+  { 0x09eb, 0x2510 }, /*               uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT */
+  { 0x09ec, 0x250c }, /*                upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */
+  { 0x09ed, 0x2514 }, /*               lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */
+  { 0x09ee, 0x253c }, /*               crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */
+/*  0x09ef                            horizlinescan1 ? ??? */
+/*  0x09f0                            horizlinescan3 ? ??? */
+  { 0x09f1, 0x2500 }, /*              horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */
+/*  0x09f2                            horizlinescan7 ? ??? */
+/*  0x09f3                            horizlinescan9 ? ??? */
+  { 0x09f4, 0x251c }, /*                       leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
+  { 0x09f5, 0x2524 }, /*                      rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */
+  { 0x09f6, 0x2534 }, /*                        bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */
+  { 0x09f7, 0x252c }, /*                        topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */
+  { 0x09f8, 0x2502 }, /*                     vertbar │ BOX DRAWINGS LIGHT VERTICAL */
+  { 0x0aa1, 0x2003 }, /*                     emspace   EM SPACE */
+  { 0x0aa2, 0x2002 }, /*                     enspace   EN SPACE */
+  { 0x0aa3, 0x2004 }, /*                    em3space   THREE-PER-EM SPACE */
+  { 0x0aa4, 0x2005 }, /*                    em4space   FOUR-PER-EM SPACE */
+  { 0x0aa5, 0x2007 }, /*                  digitspace   FIGURE SPACE */
+  { 0x0aa6, 0x2008 }, /*                  punctspace   PUNCTUATION SPACE */
+  { 0x0aa7, 0x2009 }, /*                   thinspace   THIN SPACE */
+  { 0x0aa8, 0x200a }, /*                   hairspace   HAIR SPACE */
+  { 0x0aa9, 0x2014 }, /*                      emdash — EM DASH */
+  { 0x0aaa, 0x2013 }, /*                      endash – EN DASH */
+/*  0x0aac                               signifblank ? ??? */
+  { 0x0aae, 0x2026 }, /*                    ellipsis … HORIZONTAL ELLIPSIS */
+/*  0x0aaf                           doubbaselinedot ? ??? */
+  { 0x0ab0, 0x2153 }, /*                    onethird ⅓ VULGAR FRACTION ONE THIRD */
+  { 0x0ab1, 0x2154 }, /*                   twothirds ⅔ VULGAR FRACTION TWO THIRDS */
+  { 0x0ab2, 0x2155 }, /*                    onefifth ⅕ VULGAR FRACTION ONE FIFTH */
+  { 0x0ab3, 0x2156 }, /*                   twofifths ⅖ VULGAR FRACTION TWO FIFTHS */
+  { 0x0ab4, 0x2157 }, /*                 threefifths ⅗ VULGAR FRACTION THREE FIFTHS */
+  { 0x0ab5, 0x2158 }, /*                  fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS */
+  { 0x0ab6, 0x2159 }, /*                    onesixth ⅙ VULGAR FRACTION ONE SIXTH */
+  { 0x0ab7, 0x215a }, /*                  fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */
+  { 0x0ab8, 0x2105 }, /*                      careof ℅ CARE OF */
+  { 0x0abb, 0x2012 }, /*                     figdash ‒ FIGURE DASH */
+  { 0x0abc, 0x2329 }, /*            leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */
+  { 0x0abd, 0x002e }, /*                decimalpoint . FULL STOP */
+  { 0x0abe, 0x232a }, /*           rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */
+/*  0x0abf                                    marker ? ??? */
+  { 0x0ac3, 0x215b }, /*                   oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */
+  { 0x0ac4, 0x215c }, /*                threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */
+  { 0x0ac5, 0x215d }, /*                 fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS */
+  { 0x0ac6, 0x215e }, /*                seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS */
+  { 0x0ac9, 0x2122 }, /*                   trademark ™ TRADE MARK SIGN */
+  { 0x0aca, 0x2613 }, /*               signaturemark ☓ SALTIRE */
+/*  0x0acb                         trademarkincircle ? ??? */
+  { 0x0acc, 0x25c1 }, /*            leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */
+  { 0x0acd, 0x25b7 }, /*           rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */
+  { 0x0ace, 0x25cb }, /*                emopencircle ○ WHITE CIRCLE */
+  { 0x0acf, 0x25a1 }, /*             emopenrectangle □ WHITE SQUARE */
+  { 0x0ad0, 0x2018 }, /*         leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK */
+  { 0x0ad1, 0x2019 }, /*        rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK */
+  { 0x0ad2, 0x201c }, /*         leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */
+  { 0x0ad3, 0x201d }, /*        rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */
+  { 0x0ad4, 0x211e }, /*                prescription ℞ PRESCRIPTION TAKE */
+  { 0x0ad6, 0x2032 }, /*                     minutes ′ PRIME */
+  { 0x0ad7, 0x2033 }, /*                     seconds ″ DOUBLE PRIME */
+  { 0x0ad9, 0x271d }, /*                  latincross ✝ LATIN CROSS */
+/*  0x0ada                                  hexagram ? ??? */
+  { 0x0adb, 0x25ac }, /*            filledrectbullet ▬ BLACK RECTANGLE */
+  { 0x0adc, 0x25c0 }, /*         filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */
+  { 0x0add, 0x25b6 }, /*        filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */
+  { 0x0ade, 0x25cf }, /*              emfilledcircle ● BLACK CIRCLE */
+  { 0x0adf, 0x25a0 }, /*                emfilledrect ■ BLACK SQUARE */
+  { 0x0ae0, 0x25e6 }, /*            enopencircbullet ◦ WHITE BULLET */
+  { 0x0ae1, 0x25ab }, /*          enopensquarebullet ▫ WHITE SMALL SQUARE */
+  { 0x0ae2, 0x25ad }, /*              openrectbullet ▭ WHITE RECTANGLE */
+  { 0x0ae3, 0x25b3 }, /*             opentribulletup △ WHITE UP-POINTING TRIANGLE */
+  { 0x0ae4, 0x25bd }, /*           opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE */
+  { 0x0ae5, 0x2606 }, /*                    openstar ☆ WHITE STAR */
+  { 0x0ae6, 0x2022 }, /*          enfilledcircbullet • BULLET */
+  { 0x0ae7, 0x25aa }, /*            enfilledsqbullet ▪ BLACK SMALL SQUARE */
+  { 0x0ae8, 0x25b2 }, /*           filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */
+  { 0x0ae9, 0x25bc }, /*         filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE */
+  { 0x0aea, 0x261c }, /*                 leftpointer ☜ WHITE LEFT POINTING INDEX */
+  { 0x0aeb, 0x261e }, /*                rightpointer ☞ WHITE RIGHT POINTING INDEX */
+  { 0x0aec, 0x2663 }, /*                        club ♣ BLACK CLUB SUIT */
+  { 0x0aed, 0x2666 }, /*                     diamond ♦ BLACK DIAMOND SUIT */
+  { 0x0aee, 0x2665 }, /*                       heart ♥ BLACK HEART SUIT */
+  { 0x0af0, 0x2720 }, /*                maltesecross ✠ MALTESE CROSS */
+  { 0x0af1, 0x2020 }, /*                      dagger † DAGGER */
+  { 0x0af2, 0x2021 }, /*                doubledagger ‡ DOUBLE DAGGER */
+  { 0x0af3, 0x2713 }, /*                   checkmark ✓ CHECK MARK */
+  { 0x0af4, 0x2717 }, /*                 ballotcross ✗ BALLOT X */
+  { 0x0af5, 0x266f }, /*                musicalsharp ♯ MUSIC SHARP SIGN */
+  { 0x0af6, 0x266d }, /*                 musicalflat ♭ MUSIC FLAT SIGN */
+  { 0x0af7, 0x2642 }, /*                  malesymbol ♂ MALE SIGN */
+  { 0x0af8, 0x2640 }, /*                femalesymbol ♀ FEMALE SIGN */
+  { 0x0af9, 0x260e }, /*                   telephone ☎ BLACK TELEPHONE */
+  { 0x0afa, 0x2315 }, /*           telephonerecorder ⌕ TELEPHONE RECORDER */
+  { 0x0afb, 0x2117 }, /*         phonographcopyright ℗ SOUND RECORDING COPYRIGHT */
+  { 0x0afc, 0x2038 }, /*                       caret ‸ CARET */
+  { 0x0afd, 0x201a }, /*          singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK */
+  { 0x0afe, 0x201e }, /*          doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK */
+/*  0x0aff                                    cursor ? ??? */
+  { 0x0ba3, 0x003c }, /*                   leftcaret < LESS-THAN SIGN */
+  { 0x0ba6, 0x003e }, /*                  rightcaret > GREATER-THAN SIGN */
+  { 0x0ba8, 0x2228 }, /*                   downcaret ∨ LOGICAL OR */
+  { 0x0ba9, 0x2227 }, /*                     upcaret ∧ LOGICAL AND */
+  { 0x0bc0, 0x00af }, /*                     overbar ¯ MACRON */
+  { 0x0bc2, 0x22a4 }, /*                    downtack ⊤ DOWN TACK */
+  { 0x0bc3, 0x2229 }, /*                      upshoe ∩ INTERSECTION */
+  { 0x0bc4, 0x230a }, /*                   downstile ⌊ LEFT FLOOR */
+  { 0x0bc6, 0x005f }, /*                    underbar _ LOW LINE */
+  { 0x0bca, 0x2218 }, /*                         jot ∘ RING OPERATOR */
+  { 0x0bcc, 0x2395 }, /*                        quad ⎕ APL FUNCTIONAL SYMBOL QUAD (Unicode 3.0) */
+  { 0x0bce, 0x22a5 }, /*                      uptack ⊥ UP TACK */
+  { 0x0bcf, 0x25cb }, /*                      circle ○ WHITE CIRCLE */
+  { 0x0bd3, 0x2308 }, /*                     upstile ⌈ LEFT CEILING */
+  { 0x0bd6, 0x222a }, /*                    downshoe ∪ UNION */
+  { 0x0bd8, 0x2283 }, /*                   rightshoe ⊃ SUPERSET OF */
+  { 0x0bda, 0x2282 }, /*                    leftshoe ⊂ SUBSET OF */
+  { 0x0bdc, 0x22a3 }, /*                    lefttack ⊣ LEFT TACK */
+  { 0x0bfc, 0x22a2 }, /*                   righttack ⊢ RIGHT TACK */
+  { 0x0cdf, 0x2017 }, /*        hebrew_doublelowline ‗ DOUBLE LOW LINE */
+  { 0x0ce0, 0x05d0 }, /*                hebrew_aleph א HEBREW LETTER ALEF */
+  { 0x0ce1, 0x05d1 }, /*                  hebrew_bet ב HEBREW LETTER BET */
+  { 0x0ce2, 0x05d2 }, /*                hebrew_gimel ג HEBREW LETTER GIMEL */
+  { 0x0ce3, 0x05d3 }, /*                hebrew_dalet ד HEBREW LETTER DALET */
+  { 0x0ce4, 0x05d4 }, /*                   hebrew_he ה HEBREW LETTER HE */
+  { 0x0ce5, 0x05d5 }, /*                  hebrew_waw ו HEBREW LETTER VAV */
+  { 0x0ce6, 0x05d6 }, /*                 hebrew_zain ז HEBREW LETTER ZAYIN */
+  { 0x0ce7, 0x05d7 }, /*                 hebrew_chet ח HEBREW LETTER HET */
+  { 0x0ce8, 0x05d8 }, /*                  hebrew_tet ט HEBREW LETTER TET */
+  { 0x0ce9, 0x05d9 }, /*                  hebrew_yod י HEBREW LETTER YOD */
+  { 0x0cea, 0x05da }, /*            hebrew_finalkaph ך HEBREW LETTER FINAL KAF */
+  { 0x0ceb, 0x05db }, /*                 hebrew_kaph כ HEBREW LETTER KAF */
+  { 0x0cec, 0x05dc }, /*                hebrew_lamed ל HEBREW LETTER LAMED */
+  { 0x0ced, 0x05dd }, /*             hebrew_finalmem ם HEBREW LETTER FINAL MEM */
+  { 0x0cee, 0x05de }, /*                  hebrew_mem מ HEBREW LETTER MEM */
+  { 0x0cef, 0x05df }, /*             hebrew_finalnun ן HEBREW LETTER FINAL NUN */
+  { 0x0cf0, 0x05e0 }, /*                  hebrew_nun נ HEBREW LETTER NUN */
+  { 0x0cf1, 0x05e1 }, /*               hebrew_samech ס HEBREW LETTER SAMEKH */
+  { 0x0cf2, 0x05e2 }, /*                 hebrew_ayin ע HEBREW LETTER AYIN */
+  { 0x0cf3, 0x05e3 }, /*              hebrew_finalpe ף HEBREW LETTER FINAL PE */
+  { 0x0cf4, 0x05e4 }, /*                   hebrew_pe פ HEBREW LETTER PE */
+  { 0x0cf5, 0x05e5 }, /*            hebrew_finalzade ץ HEBREW LETTER FINAL TSADI */
+  { 0x0cf6, 0x05e6 }, /*                 hebrew_zade צ HEBREW LETTER TSADI */
+  { 0x0cf7, 0x05e7 }, /*                 hebrew_qoph ק HEBREW LETTER QOF */
+  { 0x0cf8, 0x05e8 }, /*                 hebrew_resh ר HEBREW LETTER RESH */
+  { 0x0cf9, 0x05e9 }, /*                 hebrew_shin ש HEBREW LETTER SHIN */
+  { 0x0cfa, 0x05ea }, /*                  hebrew_taw ת HEBREW LETTER TAV */
+  { 0x0da1, 0x0e01 }, /*                  Thai_kokai ก THAI CHARACTER KO KAI */
+  { 0x0da2, 0x0e02 }, /*                Thai_khokhai ข THAI CHARACTER KHO KHAI */
+  { 0x0da3, 0x0e03 }, /*               Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT */
+  { 0x0da4, 0x0e04 }, /*               Thai_khokhwai ค THAI CHARACTER KHO KHWAI */
+  { 0x0da5, 0x0e05 }, /*                Thai_khokhon ฅ THAI CHARACTER KHO KHON */
+  { 0x0da6, 0x0e06 }, /*             Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG */
+  { 0x0da7, 0x0e07 }, /*                 Thai_ngongu ง THAI CHARACTER NGO NGU */
+  { 0x0da8, 0x0e08 }, /*                Thai_chochan จ THAI CHARACTER CHO CHAN */
+  { 0x0da9, 0x0e09 }, /*               Thai_choching ฉ THAI CHARACTER CHO CHING */
+  { 0x0daa, 0x0e0a }, /*               Thai_chochang ช THAI CHARACTER CHO CHANG */
+  { 0x0dab, 0x0e0b }, /*                   Thai_soso ซ THAI CHARACTER SO SO */
+  { 0x0dac, 0x0e0c }, /*                Thai_chochoe ฌ THAI CHARACTER CHO CHOE */
+  { 0x0dad, 0x0e0d }, /*                 Thai_yoying ญ THAI CHARACTER YO YING */
+  { 0x0dae, 0x0e0e }, /*                Thai_dochada ฎ THAI CHARACTER DO CHADA */
+  { 0x0daf, 0x0e0f }, /*                Thai_topatak ฏ THAI CHARACTER TO PATAK */
+  { 0x0db0, 0x0e10 }, /*                Thai_thothan ฐ THAI CHARACTER THO THAN */
+  { 0x0db1, 0x0e11 }, /*          Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO */
+  { 0x0db2, 0x0e12 }, /*             Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO */
+  { 0x0db3, 0x0e13 }, /*                  Thai_nonen ณ THAI CHARACTER NO NEN */
+  { 0x0db4, 0x0e14 }, /*                  Thai_dodek ด THAI CHARACTER DO DEK */
+  { 0x0db5, 0x0e15 }, /*                  Thai_totao ต THAI CHARACTER TO TAO */
+  { 0x0db6, 0x0e16 }, /*               Thai_thothung ถ THAI CHARACTER THO THUNG */
+  { 0x0db7, 0x0e17 }, /*              Thai_thothahan ท THAI CHARACTER THO THAHAN */
+  { 0x0db8, 0x0e18 }, /*               Thai_thothong ธ THAI CHARACTER THO THONG */
+  { 0x0db9, 0x0e19 }, /*                   Thai_nonu น THAI CHARACTER NO NU */
+  { 0x0dba, 0x0e1a }, /*               Thai_bobaimai บ THAI CHARACTER BO BAIMAI */
+  { 0x0dbb, 0x0e1b }, /*                  Thai_popla ป THAI CHARACTER PO PLA */
+  { 0x0dbc, 0x0e1c }, /*               Thai_phophung ผ THAI CHARACTER PHO PHUNG */
+  { 0x0dbd, 0x0e1d }, /*                   Thai_fofa ฝ THAI CHARACTER FO FA */
+  { 0x0dbe, 0x0e1e }, /*                Thai_phophan พ THAI CHARACTER PHO PHAN */
+  { 0x0dbf, 0x0e1f }, /*                  Thai_fofan ฟ THAI CHARACTER FO FAN */
+  { 0x0dc0, 0x0e20 }, /*             Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO */
+  { 0x0dc1, 0x0e21 }, /*                   Thai_moma ม THAI CHARACTER MO MA */
+  { 0x0dc2, 0x0e22 }, /*                  Thai_yoyak ย THAI CHARACTER YO YAK */
+  { 0x0dc3, 0x0e23 }, /*                  Thai_rorua ร THAI CHARACTER RO RUA */
+  { 0x0dc4, 0x0e24 }, /*                     Thai_ru ฤ THAI CHARACTER RU */
+  { 0x0dc5, 0x0e25 }, /*                 Thai_loling ล THAI CHARACTER LO LING */
+  { 0x0dc6, 0x0e26 }, /*                     Thai_lu ฦ THAI CHARACTER LU */
+  { 0x0dc7, 0x0e27 }, /*                 Thai_wowaen ว THAI CHARACTER WO WAEN */
+  { 0x0dc8, 0x0e28 }, /*                 Thai_sosala ศ THAI CHARACTER SO SALA */
+  { 0x0dc9, 0x0e29 }, /*                 Thai_sorusi ษ THAI CHARACTER SO RUSI */
+  { 0x0dca, 0x0e2a }, /*                  Thai_sosua ส THAI CHARACTER SO SUA */
+  { 0x0dcb, 0x0e2b }, /*                  Thai_hohip ห THAI CHARACTER HO HIP */
+  { 0x0dcc, 0x0e2c }, /*                Thai_lochula ฬ THAI CHARACTER LO CHULA */
+  { 0x0dcd, 0x0e2d }, /*                   Thai_oang อ THAI CHARACTER O ANG */
+  { 0x0dce, 0x0e2e }, /*               Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK */
+  { 0x0dcf, 0x0e2f }, /*              Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI */
+  { 0x0dd0, 0x0e30 }, /*                  Thai_saraa ะ THAI CHARACTER SARA A */
+  { 0x0dd1, 0x0e31 }, /*             Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT */
+  { 0x0dd2, 0x0e32 }, /*                 Thai_saraaa า THAI CHARACTER SARA AA */
+  { 0x0dd3, 0x0e33 }, /*                 Thai_saraam ำ THAI CHARACTER SARA AM */
+  { 0x0dd4, 0x0e34 }, /*                  Thai_sarai ิ THAI CHARACTER SARA I */
+  { 0x0dd5, 0x0e35 }, /*                 Thai_saraii ี THAI CHARACTER SARA II */
+  { 0x0dd6, 0x0e36 }, /*                 Thai_saraue ึ THAI CHARACTER SARA UE */
+  { 0x0dd7, 0x0e37 }, /*                Thai_sarauee ื THAI CHARACTER SARA UEE */
+  { 0x0dd8, 0x0e38 }, /*                  Thai_sarau ุ THAI CHARACTER SARA U */
+  { 0x0dd9, 0x0e39 }, /*                 Thai_sarauu ู THAI CHARACTER SARA UU */
+  { 0x0dda, 0x0e3a }, /*                Thai_phinthu ฺ THAI CHARACTER PHINTHU */
+  { 0x0dde, 0x0e3e }, /*      Thai_maihanakat_maitho ฾ ??? */
+  { 0x0ddf, 0x0e3f }, /*                   Thai_baht ฿ THAI CURRENCY SYMBOL BAHT */
+  { 0x0de0, 0x0e40 }, /*                  Thai_sarae เ THAI CHARACTER SARA E */
+  { 0x0de1, 0x0e41 }, /*                 Thai_saraae แ THAI CHARACTER SARA AE */
+  { 0x0de2, 0x0e42 }, /*                  Thai_sarao โ THAI CHARACTER SARA O */
+  { 0x0de3, 0x0e43 }, /*          Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN */
+  { 0x0de4, 0x0e44 }, /*         Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI */
+  { 0x0de5, 0x0e45 }, /*            Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO */
+  { 0x0de6, 0x0e46 }, /*               Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK */
+  { 0x0de7, 0x0e47 }, /*              Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU */
+  { 0x0de8, 0x0e48 }, /*                  Thai_maiek ่ THAI CHARACTER MAI EK */
+  { 0x0de9, 0x0e49 }, /*                 Thai_maitho ้ THAI CHARACTER MAI THO */
+  { 0x0dea, 0x0e4a }, /*                 Thai_maitri ๊ THAI CHARACTER MAI TRI */
+  { 0x0deb, 0x0e4b }, /*            Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA */
+  { 0x0dec, 0x0e4c }, /*            Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT */
+  { 0x0ded, 0x0e4d }, /*               Thai_nikhahit ํ THAI CHARACTER NIKHAHIT */
+  { 0x0df0, 0x0e50 }, /*                 Thai_leksun ๐ THAI DIGIT ZERO */
+  { 0x0df1, 0x0e51 }, /*                Thai_leknung ๑ THAI DIGIT ONE */
+  { 0x0df2, 0x0e52 }, /*                Thai_leksong ๒ THAI DIGIT TWO */
+  { 0x0df3, 0x0e53 }, /*                 Thai_leksam ๓ THAI DIGIT THREE */
+  { 0x0df4, 0x0e54 }, /*                  Thai_leksi ๔ THAI DIGIT FOUR */
+  { 0x0df5, 0x0e55 }, /*                  Thai_lekha ๕ THAI DIGIT FIVE */
+  { 0x0df6, 0x0e56 }, /*                 Thai_lekhok ๖ THAI DIGIT SIX */
+  { 0x0df7, 0x0e57 }, /*                Thai_lekchet ๗ THAI DIGIT SEVEN */
+  { 0x0df8, 0x0e58 }, /*                Thai_lekpaet ๘ THAI DIGIT EIGHT */
+  { 0x0df9, 0x0e59 }, /*                 Thai_lekkao ๙ THAI DIGIT NINE */
+  { 0x0ea1, 0x3131 }, /*               Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK */
+  { 0x0ea2, 0x3132 }, /*          Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK */
+  { 0x0ea3, 0x3133 }, /*           Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS */
+  { 0x0ea4, 0x3134 }, /*                Hangul_Nieun ㄴ HANGUL LETTER NIEUN */
+  { 0x0ea5, 0x3135 }, /*           Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC */
+  { 0x0ea6, 0x3136 }, /*           Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH */
+  { 0x0ea7, 0x3137 }, /*               Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT */
+  { 0x0ea8, 0x3138 }, /*          Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT */
+  { 0x0ea9, 0x3139 }, /*                Hangul_Rieul ㄹ HANGUL LETTER RIEUL */
+  { 0x0eaa, 0x313a }, /*          Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK */
+  { 0x0eab, 0x313b }, /*           Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM */
+  { 0x0eac, 0x313c }, /*           Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP */
+  { 0x0ead, 0x313d }, /*            Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS */
+  { 0x0eae, 0x313e }, /*           Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH */
+  { 0x0eaf, 0x313f }, /*          Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH */
+  { 0x0eb0, 0x3140 }, /*           Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH */
+  { 0x0eb1, 0x3141 }, /*                Hangul_Mieum ㅁ HANGUL LETTER MIEUM */
+  { 0x0eb2, 0x3142 }, /*                Hangul_Pieub ㅂ HANGUL LETTER PIEUP */
+  { 0x0eb3, 0x3143 }, /*           Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP */
+  { 0x0eb4, 0x3144 }, /*            Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS */
+  { 0x0eb5, 0x3145 }, /*                 Hangul_Sios ㅅ HANGUL LETTER SIOS */
+  { 0x0eb6, 0x3146 }, /*            Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS */
+  { 0x0eb7, 0x3147 }, /*                Hangul_Ieung ㅇ HANGUL LETTER IEUNG */
+  { 0x0eb8, 0x3148 }, /*                Hangul_Jieuj ㅈ HANGUL LETTER CIEUC */
+  { 0x0eb9, 0x3149 }, /*           Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC */
+  { 0x0eba, 0x314a }, /*                Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH */
+  { 0x0ebb, 0x314b }, /*               Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH */
+  { 0x0ebc, 0x314c }, /*                Hangul_Tieut ㅌ HANGUL LETTER THIEUTH */
+  { 0x0ebd, 0x314d }, /*               Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH */
+  { 0x0ebe, 0x314e }, /*                Hangul_Hieuh ㅎ HANGUL LETTER HIEUH */
+  { 0x0ebf, 0x314f }, /*                    Hangul_A ㅏ HANGUL LETTER A */
+  { 0x0ec0, 0x3150 }, /*                   Hangul_AE ㅐ HANGUL LETTER AE */
+  { 0x0ec1, 0x3151 }, /*                   Hangul_YA ㅑ HANGUL LETTER YA */
+  { 0x0ec2, 0x3152 }, /*                  Hangul_YAE ㅒ HANGUL LETTER YAE */
+  { 0x0ec3, 0x3153 }, /*                   Hangul_EO ㅓ HANGUL LETTER EO */
+  { 0x0ec4, 0x3154 }, /*                    Hangul_E ㅔ HANGUL LETTER E */
+  { 0x0ec5, 0x3155 }, /*                  Hangul_YEO ㅕ HANGUL LETTER YEO */
+  { 0x0ec6, 0x3156 }, /*                   Hangul_YE ㅖ HANGUL LETTER YE */
+  { 0x0ec7, 0x3157 }, /*                    Hangul_O ㅗ HANGUL LETTER O */
+  { 0x0ec8, 0x3158 }, /*                   Hangul_WA ㅘ HANGUL LETTER WA */
+  { 0x0ec9, 0x3159 }, /*                  Hangul_WAE ㅙ HANGUL LETTER WAE */
+  { 0x0eca, 0x315a }, /*                   Hangul_OE ㅚ HANGUL LETTER OE */
+  { 0x0ecb, 0x315b }, /*                   Hangul_YO ㅛ HANGUL LETTER YO */
+  { 0x0ecc, 0x315c }, /*                    Hangul_U ㅜ HANGUL LETTER U */
+  { 0x0ecd, 0x315d }, /*                  Hangul_WEO ㅝ HANGUL LETTER WEO */
+  { 0x0ece, 0x315e }, /*                   Hangul_WE ㅞ HANGUL LETTER WE */
+  { 0x0ecf, 0x315f }, /*                   Hangul_WI ㅟ HANGUL LETTER WI */
+  { 0x0ed0, 0x3160 }, /*                   Hangul_YU ㅠ HANGUL LETTER YU */
+  { 0x0ed1, 0x3161 }, /*                   Hangul_EU ㅡ HANGUL LETTER EU */
+  { 0x0ed2, 0x3162 }, /*                   Hangul_YI ㅢ HANGUL LETTER YI */
+  { 0x0ed3, 0x3163 }, /*                    Hangul_I ㅣ HANGUL LETTER I */
+  { 0x0ed4, 0x11a8 }, /*             Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK */
+  { 0x0ed5, 0x11a9 }, /*        Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK */
+  { 0x0ed6, 0x11aa }, /*         Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS */
+  { 0x0ed7, 0x11ab }, /*              Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN */
+  { 0x0ed8, 0x11ac }, /*         Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC */
+  { 0x0ed9, 0x11ad }, /*         Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH */
+  { 0x0eda, 0x11ae }, /*             Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT */
+  { 0x0edb, 0x11af }, /*              Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL */
+  { 0x0edc, 0x11b0 }, /*        Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK */
+  { 0x0edd, 0x11b1 }, /*         Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM */
+  { 0x0ede, 0x11b2 }, /*         Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP */
+  { 0x0edf, 0x11b3 }, /*          Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS */
+  { 0x0ee0, 0x11b4 }, /*         Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH */
+  { 0x0ee1, 0x11b5 }, /*        Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH */
+  { 0x0ee2, 0x11b6 }, /*         Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH */
+  { 0x0ee3, 0x11b7 }, /*              Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM */
+  { 0x0ee4, 0x11b8 }, /*              Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP */
+  { 0x0ee5, 0x11b9 }, /*          Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS */
+  { 0x0ee6, 0x11ba }, /*               Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS */
+  { 0x0ee7, 0x11bb }, /*          Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS */
+  { 0x0ee8, 0x11bc }, /*              Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG */
+  { 0x0ee9, 0x11bd }, /*              Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC */
+  { 0x0eea, 0x11be }, /*              Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH */
+  { 0x0eeb, 0x11bf }, /*             Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH */
+  { 0x0eec, 0x11c0 }, /*              Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH */
+  { 0x0eed, 0x11c1 }, /*             Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */
+  { 0x0eee, 0x11c2 }, /*              Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */
+  { 0x0eef, 0x316d }, /*     Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH */
+  { 0x0ef0, 0x3171 }, /*    Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */
+  { 0x0ef1, 0x3178 }, /*    Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */
+  { 0x0ef2, 0x317f }, /*              Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */
+/*  0x0ef3                  Hangul_KkogjiDalrinIeung ? ??? */
+  { 0x0ef4, 0x3184 }, /*   Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */
+  { 0x0ef5, 0x3186 }, /*          Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */
+  { 0x0ef6, 0x318d }, /*                Hangul_AraeA ㆍ HANGUL LETTER ARAEA */
+  { 0x0ef7, 0x318e }, /*               Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */
+  { 0x0ef8, 0x11eb }, /*            Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */
+/*  0x0ef9                Hangul_J_KkogjiDalrinIeung ? ??? */
+  { 0x0efa, 0x11f9 }, /*        Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */
+  { 0x0eff, 0x20a9 }, /*                  Korean_Won ₩ WON SIGN */
+  { 0x13bc, 0x0152 }, /*                          OE Œ LATIN CAPITAL LIGATURE OE */
+  { 0x13bd, 0x0153 }, /*                          oe œ LATIN SMALL LIGATURE OE */
+  { 0x13be, 0x0178 }, /*                  Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */
+  { 0x20a0, 0x20a0 }, /*                     EcuSign ₠ EURO-CURRENCY SIGN */
+  { 0x20a1, 0x20a1 }, /*                   ColonSign ₡ COLON SIGN */
+  { 0x20a2, 0x20a2 }, /*                CruzeiroSign ₢ CRUZEIRO SIGN */
+  { 0x20a3, 0x20a3 }, /*                  FFrancSign ₣ FRENCH FRANC SIGN */
+  { 0x20a4, 0x20a4 }, /*                    LiraSign ₤ LIRA SIGN */
+  { 0x20a5, 0x20a5 }, /*                    MillSign ₥ MILL SIGN */
+  { 0x20a6, 0x20a6 }, /*                   NairaSign ₦ NAIRA SIGN */
+  { 0x20a7, 0x20a7 }, /*                  PesetaSign ₧ PESETA SIGN */
+  { 0x20a8, 0x20a8 }, /*                   RupeeSign ₨ RUPEE SIGN */
+  { 0x20a9, 0x20a9 }, /*                     WonSign ₩ WON SIGN */
+  { 0x20aa, 0x20aa }, /*               NewSheqelSign ₪ NEW SHEQEL SIGN */
+  { 0x20ab, 0x20ab }, /*                    DongSign ₫ DONG SIGN */
+  { 0x20ac, 0x20ac }, /*                    EuroSign € EURO SIGN */
+};
+
+long keysym2ucs(KeySym keysym)
+{
+    int min = 0;
+    int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
+    int mid;
+
+    /* first check for Latin-1 characters (1:1 mapping) */
+    if ((keysym >= 0x0020 && keysym <= 0x007e) ||
+        (keysym >= 0x00a0 && keysym <= 0x00ff))
+        return keysym;
+
+    /* also check for directly encoded 24-bit UCS characters */
+    if ((keysym & 0xff000000) == 0x01000000)
+        return keysym & 0x00ffffff;
+
+    /* binary search in table */
+    while (max >= min) {
+        mid = (min + max) / 2;
+        if (keysymtab[mid].keysym < keysym)
+            min = mid + 1;
+        else if (keysymtab[mid].keysym > keysym)
+            max = mid - 1;
+        else {
+            /* found it */
+            return keysymtab[mid].ucs;
+        }
+    }
+
+    /* no matching Unicode value found */
+    return -1;
+}
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/keysym2ucs.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/*
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is from xterm-122 source XFree86:
+ *  xc/programs/xterm/keysym2ucs.h,v 1.1 1999/06/12 15:37:18 dawes Exp.
+ *
+ * The Initial Developer of the Original Code is
+ * Markus G. Kuhn <mkuhn@acm.org> and Richard Verhoeven <river@win.tue.nl>.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Frank Tang <ftang@netscape.com> adopt into mozilla
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/*
+ * This module converts keysym values into the corresponding ISO 10646-1
+ * (UCS, Unicode) values.
+ */
+
+#include <X11/X.h>
+
+#ifdef __cplusplus
+extern "C" { 
+#endif
+
+long keysym2ucs(KeySym keysym); 
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/mozqwidget.cpp
@@ -0,0 +1,273 @@
+#include "mozqwidget.h"
+#include "nsWindow.h"
+#include <qevent.h>
+
+MozQWidget::MozQWidget(nsWindow *receiver, QWidget *parent,
+                       const char *name, int f)
+    : QWidget(parent, (Qt::WindowFlags)f),
+      mReceiver(receiver)
+{
+    setAttribute(Qt::WA_QuitOnClose, false);
+}
+
+bool MozQWidget::event(QEvent *e)
+{
+    nsEventStatus status = nsEventStatus_eIgnore;
+    bool handled = true;
+
+    if (!mReceiver)
+        return false;
+
+    switch(e->type()) {
+/*
+    case QEvent::Accessibility:
+    {
+        qDebug("accessibility event received");
+    }
+    break;
+*/
+    case QEvent::MouseButtonPress:
+    {
+        QMouseEvent *ms = (QMouseEvent*)(e);
+        status = mReceiver->OnButtonPressEvent(ms);
+    }
+    break;
+    case QEvent::MouseButtonRelease:
+    {
+        QMouseEvent *ms = (QMouseEvent*)(e);
+        status = mReceiver->OnButtonReleaseEvent(ms);
+    }
+    break;
+    case QEvent::MouseButtonDblClick:
+    {
+        QMouseEvent *ms = (QMouseEvent*)(e);
+        status = mReceiver->mouseDoubleClickEvent(ms);
+    }
+    break;
+    case QEvent::MouseMove:
+    {
+        QMouseEvent *ms = (QMouseEvent*)(e);
+        status = mReceiver->OnMotionNotifyEvent(ms);
+    }
+    break;
+    case QEvent::KeyPress:
+    {
+        QKeyEvent *kev = (QKeyEvent*)(e);
+        status = mReceiver->OnKeyPressEvent(kev);
+    }
+    break;
+    case QEvent::KeyRelease:
+    {
+        QKeyEvent *kev = (QKeyEvent*)(e);
+        status = mReceiver->OnKeyReleaseEvent(kev);
+    }
+    break;
+/*
+    case QEvent::IMStart:
+    {
+        QIMEvent *iev = (QIMEvent*)(e);
+        status = mReceiver->imStartEvent(iev);
+    }
+    break;
+    case QEvent::IMCompose:
+    {
+        QIMEvent *iev = (QIMEvent*)(e);
+        status = mReceiver->imComposeEvent(iev);
+    }
+    break;
+    case QEvent::IMEnd:
+    {
+        QIMEvent *iev = (QIMEvent*)(e);
+        status = mReceiver->imEndEvent(iev);
+    }
+    break;
+*/
+    case QEvent::FocusIn:
+    {
+        QFocusEvent *fev = (QFocusEvent*)(e);
+        mReceiver->OnFocusInEvent(fev);
+        return TRUE;
+    }
+    break;
+    case QEvent::FocusOut:
+    {
+        QFocusEvent *fev = (QFocusEvent*)(e);
+        mReceiver->OnFocusOutEvent(fev);
+        return TRUE;
+    }
+    break;
+    case QEvent::Enter:
+    {
+        status = mReceiver->OnEnterNotifyEvent(e);
+    }
+    break;
+    case QEvent::Leave:
+    {
+        status = mReceiver->OnLeaveNotifyEvent(e);
+    }
+    break;
+    case QEvent::Paint:
+    {
+        QPaintEvent *ev = (QPaintEvent*)(e);
+        status = mReceiver->OnPaintEvent(ev);
+    }
+    break;
+    case QEvent::Move:
+    {
+        QMoveEvent *mev = (QMoveEvent*)(e);
+        status = mReceiver->OnMoveEvent(mev);
+    }
+    break;
+    case QEvent::Resize:
+    {
+        QResizeEvent *rev = (QResizeEvent*)(e);
+        status = mReceiver->OnResizeEvent(rev);
+    }
+        break;
+    case QEvent::Show:
+    {
+        QShowEvent *sev = (QShowEvent*)(e);
+        mReceiver->showEvent(sev);
+    }
+    break;
+    case QEvent::Hide:
+    {
+        QHideEvent *hev = (QHideEvent*)(e);
+        status = mReceiver->hideEvent(hev);
+    }
+        break;
+    case QEvent::Close:
+    {
+        QCloseEvent *cev = (QCloseEvent*)(e);
+        status = mReceiver->OnCloseEvent(cev);
+    }
+    break;
+    case QEvent::Wheel:
+    {
+        QWheelEvent *wev = (QWheelEvent*)(e);
+        status = mReceiver->OnScrollEvent(wev);
+    }
+    break;
+    case QEvent::ContextMenu:
+    {
+        QContextMenuEvent *cev = (QContextMenuEvent*)(e);
+        status = mReceiver->contextMenuEvent(cev);
+    }
+    break;
+    case QEvent::DragEnter:
+    {
+        QDragEnterEvent *dev = (QDragEnterEvent*)(e);
+        status = mReceiver->OnDragEnter(dev);
+    }
+        break;
+    case QEvent::DragMove:
+    {
+        QDragMoveEvent *dev = (QDragMoveEvent*)(e);
+        status = mReceiver->OnDragMotionEvent(dev);
+    }
+    break;
+    case QEvent::DragLeave:
+    {
+        QDragLeaveEvent *dev = (QDragLeaveEvent*)(e);
+        status = mReceiver->OnDragLeaveEvent(dev);
+    }
+    break;
+    case QEvent::Drop:
+    {
+        QDropEvent *dev = (QDropEvent*)(e);
+        status = mReceiver->OnDragDropEvent(dev);
+    }
+    break;
+    default:
+        handled = false;
+        break;
+    }
+
+    if (handled)
+        return true;
+
+    return QWidget::event(e);
+
+#if 0
+    // If we were going to ignore this event, pass it up to the parent
+    // and return its value
+    if (status == nsEventStatus_eIgnore)
+        return QWidget::event(e);
+
+    // Otherwise, we know we already consumed it -- we just need to know
+    // whether we want default handling or not
+    if (status == nsEventStatus_eConsumeDoDefault)
+        QWidget::event(e);
+
+    return true;
+#endif
+}
+
+bool
+MozQWidget::SetCursor(nsCursor aCursor)
+{
+    Qt::CursorShape cursor = Qt::ArrowCursor;
+    switch(aCursor) {
+    case eCursor_standard:
+        cursor = Qt::ArrowCursor;
+        break;
+    case eCursor_wait:
+        cursor = Qt::WaitCursor;
+        break;
+    case eCursor_select:
+        cursor = Qt::IBeamCursor;
+        break;
+    case eCursor_hyperlink:
+        cursor = Qt::PointingHandCursor;
+        break;
+    case eCursor_ew_resize:
+        cursor = Qt::SplitHCursor;
+        break;
+    case eCursor_ns_resize:
+        cursor = Qt::SplitVCursor;
+        break;
+    case eCursor_nw_resize:
+    case eCursor_se_resize:
+        cursor = Qt::SizeBDiagCursor;
+        break;
+    case eCursor_ne_resize:
+    case eCursor_sw_resize:
+        cursor = Qt::SizeFDiagCursor;
+        break;
+    case eCursor_crosshair:
+    case eCursor_move:
+        cursor = Qt::SizeAllCursor;
+        break;
+    case eCursor_help:
+        cursor = Qt::WhatsThisCursor;
+        break;
+    case eCursor_copy:
+    case eCursor_alias:
+        break;
+    case eCursor_context_menu:
+    case eCursor_cell:
+    case eCursor_grab:
+    case eCursor_grabbing:
+    case eCursor_spinning:
+    case eCursor_zoom_in:
+    case eCursor_zoom_out:
+
+    default:
+        break;
+    }
+
+    // qDebug("FIXME:>>>>>>Func:%s::%d, cursor:%i, aCursor:%i\n", __PRETTY_FUNCTION__, __LINE__, cursor, aCursor);
+    // FIXME after reimplementation of whole nsWindow SetCursor cause lot of errors
+    setCursor(cursor);
+
+    return NS_OK;
+}
+
+void MozQWidget::setModal(bool modal)
+{
+    if (modal)
+        setWindowModality(Qt::ApplicationModal);
+    else
+        setWindowModality(Qt::NonModal);
+}
+
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/mozqwidget.h
@@ -0,0 +1,31 @@
+#ifndef MOZQWIDGET_H
+#define MOZQWIDGET_H
+
+#include <qwidget.h>
+#include "nsIWidget.h"
+
+class QEvent;
+class nsWindow;
+
+class MozQWidget : public QWidget
+{
+    Q_OBJECT
+public:
+    MozQWidget(nsWindow* receiver, QWidget *parent,
+               const char *name, int f);
+
+    /**
+     * Mozilla helper.
+     */
+    void setModal(bool);
+    bool SetCursor(nsCursor aCursor);
+    void dropReceiver() { mReceiver = 0x0; };
+    nsWindow* getReceiver() { return mReceiver; };
+
+protected:
+    virtual bool event(QEvent *ev);
+private:
+    nsWindow *mReceiver;
+};
+
+#endif
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsAppShell.cpp
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ *  Oleg Romashin <romaxa@gmail.com>.
+ *
+ * Contributor(s):
+ *  Oleg Romashin <romaxa@gmail.com>.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsAppShell.h"
+#include <qapplication.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <qabstracteventdispatcher.h>
+
+#include "prenv.h"
+
+#ifdef MOZ_LOGGING
+#define FORCE_PR_LOG
+#include "prlog.h"
+#endif
+
+#ifdef PR_LOGGING
+PRLogModuleInfo *gWidgetLog = nsnull;
+PRLogModuleInfo *gWidgetFocusLog = nsnull;
+PRLogModuleInfo *gWidgetIMLog = nsnull;
+PRLogModuleInfo *gWidgetDrawLog = nsnull;
+#endif
+
+static int sPokeEvent;
+
+nsAppShell::~nsAppShell()
+{
+}
+
+nsresult
+nsAppShell::Init()
+{
+#ifdef PR_LOGGING
+    if (!gWidgetLog)
+        gWidgetLog = PR_NewLogModule("Widget");
+    if (!gWidgetFocusLog)
+        gWidgetFocusLog = PR_NewLogModule("WidgetFocus");
+    if (!gWidgetIMLog)
+        gWidgetIMLog = PR_NewLogModule("WidgetIM");
+    if (!gWidgetDrawLog)
+        gWidgetDrawLog = PR_NewLogModule("WidgetDraw");
+#endif
+#if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0))
+    sPokeEvent = QEvent::registerEventType();
+#else
+    sPokeEvent = QEvent::User+5000;
+#endif
+    return nsBaseAppShell::Init();
+}
+
+void
+nsAppShell::ScheduleNativeEventCallback()
+{
+    QCoreApplication::postEvent(this,
+                                new QEvent((QEvent::Type) sPokeEvent));
+}
+
+
+PRBool
+nsAppShell::ProcessNextNativeEvent(PRBool mayWait)
+{
+   QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents;
+     
+     if (mayWait)
+         flags |= QEventLoop::WaitForMoreEvents;
+     
+     
+     QAbstractEventDispatcher *dispatcher =  QAbstractEventDispatcher::instance(qApp->thread());
+     if (!dispatcher)
+         return PR_FALSE ;
+     
+     return dispatcher->processEvents(flags)?PR_TRUE:PR_FALSE;
+
+}
+
+bool
+nsAppShell::event (QEvent *e)
+{
+    if (e->type() == sPokeEvent) {
+        NativeEventCallback();
+        return true;
+    }
+
+    return false;
+}
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsAppShell.h
@@ -0,0 +1,71 @@
+/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ *   Oleg Romashin <romaxa@gmail.com>
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Oleg Romashin <romaxa@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsAppShell_h__
+#define nsAppShell_h__
+
+#include "nsBaseAppShell.h"
+#include "nsCOMPtr.h"
+#include <qsocketnotifier.h>
+
+
+/**
+ * Native QT Application shell wrapper
+ */
+
+class nsAppShell : public QObject,
+                   public nsBaseAppShell
+{
+  Q_OBJECT
+
+public:
+  nsAppShell() { };
+
+  nsresult Init();
+
+  virtual bool event (QEvent *e);
+
+protected:
+  virtual void ScheduleNativeEventCallback();
+  virtual PRBool ProcessNextNativeEvent(PRBool mayWait);
+  virtual ~nsAppShell();
+};
+
+
+#endif // nsAppShell_h__
+
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsBidiKeyboard.cpp
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Christopher Blizzard
+ * <blizzard@mozilla.org>.  Portions created by the Initial Developer
+ * are Copyright (C) 2001 the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsBidiKeyboard.h"
+
+#include <Qt>
+#include <QApplication>
+
+NS_IMPL_ISUPPORTS1(nsBidiKeyboard, nsIBidiKeyboard)
+
+nsBidiKeyboard::nsBidiKeyboard() : nsIBidiKeyboard()
+{
+}
+
+nsBidiKeyboard::~nsBidiKeyboard()
+{
+}
+
+NS_IMETHODIMP nsBidiKeyboard::IsLangRTL(PRBool *aIsRTL)
+{
+    *aIsRTL = PR_FALSE;
+
+    Qt::LayoutDirection layoutDir = QApplication::keyboardInputDirection();
+
+    if (layoutDir == Qt::RightToLeft) {
+        *aIsRTL = PR_TRUE;
+    }
+    
+    return NS_OK;
+}
+
+NS_IMETHODIMP nsBidiKeyboard::SetLangFromBidiLevel(PRUint8 aLevel)
+{
+    return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsBidiKeyboard.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Christopher Blizzard
+ * <blizzard@mozilla.org>.  Portions created by the Initial Developer
+ * are Copyright (C) 2001 the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __nsBidiKeyboard
+#define __nsBidiKeyboard
+#include "nsIBidiKeyboard.h"
+
+class nsBidiKeyboard : public nsIBidiKeyboard
+{
+public:
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIBIDIKEYBOARD
+
+    nsBidiKeyboard();
+    virtual ~nsBidiKeyboard();
+};
+
+
+#endif // __nsBidiKeyboard
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsClipboard.cpp
@@ -0,0 +1,399 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Lars Knoll <knoll@kde.org>
+ *   Zack Rusin <zack@kde.org>
+ *   Denis Issoupov <denis@macadamian.com>
+ *   John C. Griggs <johng@corel.com>
+ *   Dan Rosen <dr@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <QApplication>
+#include <QMimeData>
+#include <QString>
+#include <QStringList>
+
+#include "nsClipboard.h"
+#include "nsISupportsPrimitives.h"
+#include "nsXPIDLString.h"
+#include "nsPrimitiveHelpers.h"
+
+NS_IMPL_ISUPPORTS1(nsClipboard, nsIClipboard)
+
+//-------------------------------------------------------------------------
+//
+// nsClipboard constructor
+//
+//-------------------------------------------------------------------------
+nsClipboard::nsClipboard() : nsIClipboard(),
+                             mSelectionOwner(nsnull),
+                             mGlobalOwner(nsnull),
+                             mSelectionTransferable(nsnull),
+                             mGlobalTransferable(nsnull)
+{
+    // No implementation needed
+}
+
+//-------------------------------------------------------------------------
+//
+// nsClipboard destructor
+//
+//-------------------------------------------------------------------------
+nsClipboard::~nsClipboard()
+{
+}
+
+
+// nsClipboard::SetNativeClipboardData ie. Copy
+
+NS_IMETHODIMP
+nsClipboard::SetNativeClipboardData( nsITransferable *aTransferable,
+                                     QClipboard::Mode clipboardMode )
+{
+    if (nsnull == aTransferable)
+    {
+        qDebug("nsClipboard::SetNativeClipboardData(): no transferable!");
+        return NS_ERROR_FAILURE;
+    }
+
+    // get flavor list that includes all flavors that can be written (including
+    // ones obtained through conversion)
+    nsCOMPtr<nsISupportsArray> flavorList;
+    nsresult errCode = aTransferable->FlavorsTransferableCanExport( getter_AddRefs(flavorList) );
+
+    if (NS_FAILED(errCode))
+    {
+        qDebug("nsClipboard::SetNativeClipboardData(): no FlavorsTransferable !");
+        return NS_ERROR_FAILURE;
+    }
+
+    QClipboard *cb = QApplication::clipboard();
+    PRUint32 flavorCount = 0;
+    flavorList->Count(&flavorCount);
+
+    for (PRUint32 i = 0; i < flavorCount; ++i)
+    {
+        nsCOMPtr<nsISupports> genericFlavor;
+        flavorList->GetElementAt(i,getter_AddRefs(genericFlavor));
+        nsCOMPtr<nsISupportsCString> currentFlavor(do_QueryInterface(genericFlavor));
+        
+        if (currentFlavor)
+        {
+            // flavorStr is the mime type
+            nsXPIDLCString flavorStr;
+            currentFlavor->ToString(getter_Copies(flavorStr));
+
+            // Clip is the data which will be sent to the clipboard
+            nsCOMPtr<nsISupports> clip;
+            // len is the length of the data
+            PRUint32 len;
+
+            // Unicode text?
+            if (!strcmp(flavorStr.get(), kUnicodeMime))
+            {
+                aTransferable->GetTransferData(flavorStr,getter_AddRefs(clip),&len);
+                nsCOMPtr<nsISupportsString> wideString;
+                wideString = do_QueryInterface(clip);
+                if (!wideString)
+                {
+                    return NS_ERROR_FAILURE;
+                }
+
+                nsAutoString utf16string;
+                wideString->GetData(utf16string);
+                QString str = QString::fromUtf16(utf16string.get());
+
+                // Set the date to the clipboard
+                cb->setText(str, clipboardMode);
+                break;
+            }
+
+            if ( !strcmp(flavorStr.get(), kNativeImageMime)
+              || !strcmp(flavorStr.get(), kPNGImageMime)
+              || !strcmp(flavorStr.get(), kJPEGImageMime)
+              || !strcmp(flavorStr.get(), kGIFImageMime))
+            {
+                qDebug("nsClipboard::SetNativeClipboardData(): Copying image data not implemented!");
+            }
+        }
+    }
+
+    return NS_OK;
+}
+
+// nsClipboard::GetNativeClipboardData ie. Paste
+//
+NS_IMETHODIMP
+nsClipboard::GetNativeClipboardData(nsITransferable *aTransferable,
+                                    QClipboard::Mode clipboardMode)
+{
+    if (nsnull == aTransferable)
+    {
+        qDebug("  GetNativeClipboardData: Transferable is null!");
+        return NS_ERROR_FAILURE;
+    }
+
+    // get flavor list that includes all acceptable flavors (including
+    // ones obtained through conversion)
+    nsCOMPtr<nsISupportsArray> flavorList;
+    nsresult errCode = aTransferable->FlavorsTransferableCanImport(
+        getter_AddRefs(flavorList));
+
+    if (NS_FAILED(errCode))
+    {
+        qDebug("nsClipboard::GetNativeClipboardData(): no FlavorsTransferable %i !",
+               errCode);
+        return NS_ERROR_FAILURE;
+    }
+
+    QClipboard *cb = QApplication::clipboard();
+    const QMimeData *mimeData = cb->mimeData(clipboardMode);
+
+    // Walk through flavors and see which flavor matches the one being pasted
+    PRUint32 flavorCount;
+    flavorList->Count(&flavorCount);
+    nsCAutoString foundFlavor;
+
+    for (PRUint32 i = 0; i < flavorCount; ++i)
+    {
+        nsCOMPtr<nsISupports> genericFlavor;
+        flavorList->GetElementAt(i,getter_AddRefs(genericFlavor));
+        nsCOMPtr<nsISupportsCString> currentFlavor(do_QueryInterface( genericFlavor) );
+
+        if (currentFlavor)
+        {
+            nsXPIDLCString flavorStr;
+            currentFlavor->ToString(getter_Copies(flavorStr));
+
+            // Ok, so which flavor the data being pasted could be?
+            // Text?
+            if (!strcmp(flavorStr.get(), kUnicodeMime)) 
+            {
+                if (mimeData->hasText())
+                {
+                    // Clipboard has text and flavor accepts text, so lets
+                    // handle the data as text
+                    foundFlavor = nsCAutoString(flavorStr);
+
+                    // Get the text data from clipboard
+                    QString text = mimeData->text();
+                    const QChar *unicode = text.unicode();
+                    // Is there a more correct way to get the size in UTF16?
+                    PRUint32 len = (PRUint32) 2*text.size();
+
+                    // And then to genericDataWrapper
+                    nsCOMPtr<nsISupports> genericDataWrapper;
+                    nsPrimitiveHelpers::CreatePrimitiveForData(
+                        foundFlavor.get(),
+                        (void*)unicode,
+                        len,
+                        getter_AddRefs(genericDataWrapper));
+
+                    // Data is good, set it to the transferable
+                    aTransferable->SetTransferData(foundFlavor.get(),
+                                                   genericDataWrapper,len);
+                    // And thats all
+                    break;
+                }
+            }
+
+            // Image?
+            if (!strcmp(flavorStr.get(), kJPEGImageMime)
+             || !strcmp(flavorStr.get(), kPNGImageMime)
+             || !strcmp(flavorStr.get(), kGIFImageMime))
+            {
+                qDebug("nsClipboard::GetNativeClipboardData(): Pasting image data not implemented!");
+                break;
+            }
+        }
+    }
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsClipboard::HasDataMatchingFlavors(const char** aFlavorList, PRUint32 aLength,
+                                    PRInt32 aWhichClipboard, PRBool *_retval)
+{
+    *_retval = PR_FALSE;
+    if (aWhichClipboard != kGlobalClipboard)
+        return NS_OK;
+
+    // Which kind of data in the clipboard
+    QClipboard *cb = QApplication::clipboard();
+    const QMimeData *mimeData = cb->mimeData();
+    const char *flavor=NULL;
+    QStringList formats = mimeData->formats();
+    // Temp QString for comparison
+    QString utf8text("text/plain;charset=utf-8");
+    // And is there matching flavor?
+    for (PRUint32 i = 0; i < aLength; ++i)
+    {
+        flavor = aFlavorList[i];
+        if (flavor)
+        {
+            QString qflavor(flavor);
+
+            if (strcmp(flavor,kTextMime) == 0)
+            {
+                NS_WARNING("DO NOT USE THE text/plain DATA FLAVOR ANY MORE. USE text/unicode INSTEAD");
+            }
+
+            // QClipboard says it has text/plain;charset=utf-8 data, mozilla wants to
+            // know if the data is text/unicode -> interpret text/plain;charset=utf-8 to text/unicode
+            if (formats.contains(qflavor) ||
+                ((strcmp(flavor, kUnicodeMime) == 0) && formats.contains(utf8text)))
+            {
+                // A match has been found, return'
+                *_retval = PR_TRUE;
+                break;
+            }
+        }
+    }
+    return NS_OK;
+}
+
+/**
+ * Sets the transferable object
+ */
+NS_IMETHODIMP
+nsClipboard::SetData(nsITransferable *aTransferable,
+                     nsIClipboardOwner *aOwner,
+                     PRInt32 aWhichClipboard)
+{
+    // See if we can short cut
+    if (
+        (aWhichClipboard == kGlobalClipboard
+           && aTransferable == mGlobalTransferable.get()
+           && aOwner == mGlobalOwner.get()
+        )
+       ||
+        (aWhichClipboard == kSelectionClipboard
+         && aTransferable == mSelectionTransferable.get()
+         && aOwner == mSelectionOwner.get()
+        )
+       )
+    {
+        return NS_OK;
+    }
+
+    EmptyClipboard(aWhichClipboard);
+
+    QClipboard::Mode mode;
+
+    if (kGlobalClipboard == aWhichClipboard)
+    {
+        mGlobalOwner = aOwner;
+        mGlobalTransferable = aTransferable;
+
+        mode = QClipboard::Clipboard;
+    }
+    else
+    {
+        mSelectionOwner = aOwner;
+        mSelectionTransferable = aTransferable;
+
+        mode = QClipboard::Selection;
+    }
+    return SetNativeClipboardData( aTransferable, mode );
+}
+
+/**
+ * Gets the transferable object
+ */
+NS_IMETHODIMP
+nsClipboard::GetData(nsITransferable *aTransferable, PRInt32 aWhichClipboard)
+{
+    if (nsnull != aTransferable)
+    {
+        QClipboard::Mode mode;
+        if (kGlobalClipboard == aWhichClipboard)
+        {
+            mode = QClipboard::Clipboard;
+        }
+        else
+        {
+            mode = QClipboard::Selection;
+        }
+        return GetNativeClipboardData(aTransferable, mode);
+    }
+    else
+    {
+        qDebug("  nsClipboard::GetData(), aTransferable is NULL.");
+    }
+    return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsClipboard::EmptyClipboard(PRInt32 aWhichClipboard)
+{
+    if (aWhichClipboard == kSelectionClipboard)
+    {
+        if (mSelectionOwner)
+        {
+            mSelectionOwner->LosingOwnership(mSelectionTransferable);
+            mSelectionOwner = nsnull;
+        }
+        mSelectionTransferable = nsnull;
+    }
+    else
+    {
+        if (mGlobalOwner)
+        {
+            mGlobalOwner->LosingOwnership(mGlobalTransferable);
+            mGlobalOwner = nsnull;
+        }
+        mGlobalTransferable = nsnull;
+    }
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsClipboard::SupportsSelectionClipboard(PRBool *_retval)
+{
+    NS_ENSURE_ARG_POINTER(_retval);
+
+    QClipboard *cb = QApplication::clipboard();
+    if (cb->supportsSelection())
+    {
+        *_retval = PR_TRUE; // we support the selection clipboard 
+    }
+    else
+    {
+        *_retval = PR_FALSE;
+    }
+
+    return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsClipboard.h
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Denis Issoupov <denis@macadamian.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nsClipboard_h__
+#define nsClipboard_h__
+
+#include "nsIClipboard.h"
+#include "nsITransferable.h"
+#include "nsIClipboardOwner.h"
+#include "nsCOMPtr.h"
+
+#include <qclipboard.h>
+
+/* Native Qt Clipboard wrapper */
+class nsClipboard : public nsIClipboard
+{
+public:
+    nsClipboard();
+    virtual ~nsClipboard();
+
+    //nsISupports
+    NS_DECL_ISUPPORTS
+
+    // nsIClipboard
+    NS_DECL_NSICLIPBOARD
+
+protected:
+    NS_IMETHOD SetNativeClipboardData(nsITransferable *aTransferable,
+                                      QClipboard::Mode cbMode);
+    NS_IMETHOD GetNativeClipboardData(nsITransferable *aTransferable,
+                                      QClipboard::Mode cbMode);
+
+    nsCOMPtr<nsIClipboardOwner> mSelectionOwner;
+    nsCOMPtr<nsIClipboardOwner> mGlobalOwner;
+    nsCOMPtr<nsITransferable>   mSelectionTransferable;
+    nsCOMPtr<nsITransferable>   mGlobalTransferable;
+};
+
+#endif // nsClipboard_h__
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsCommonWidget.cpp
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Christopher Blizzard
+ * <blizzard@mozilla.org>.  Portions created by the Initial Developer
+ * are Copyright (C) 2001 the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsCommonWidget.h"
+#include "nsQtKeyUtils.h"
+
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsCommonWidget.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Christopher Blizzard
+ * <blizzard@mozilla.org>.  Portions created by the Initial Developer
+ * are Copyright (C) 2001 the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __nsCommonWidget_h__
+#define __nsCommonWidget_h__
+
+
+
+class nsCommonWidget : public nsBaseWidget {
+public:
+    nsCommonWidget();
+    virtual ~nsCommonWidget();
+
+
+protected:
+};
+
+#endif /* __nsCommonWidget_h__ */
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsDragService.cpp
@@ -0,0 +1,300 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ *  Oleg Romashin <romaxa@gmail.com>.
+ *
+ * Contributor(s):
+ *  Oleg Romashin <romaxa@gmail.com>.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsDragService.h"
+#include "nsISupportsPrimitives.h"
+#include "nsXPIDLString.h"
+
+#include "qmimedata.h"
+#include "qwidget.h"
+
+NS_IMPL_ADDREF_INHERITED(nsDragService, nsBaseDragService)
+NS_IMPL_RELEASE_INHERITED(nsDragService, nsBaseDragService)
+NS_IMPL_QUERY_INTERFACE2(nsDragService, nsIDragService, nsIDragSession )
+
+nsDragService::nsDragService() : mDrag(NULL)
+{
+    /* member initializers and constructor code */
+        
+    // TODO: Any other better source? (the main window?)
+    //mHiddenWidget = new QWidget(0,QWidget::tr("DragDrop"),0);
+    mHiddenWidget = new QWidget();
+}
+
+nsDragService::~nsDragService()
+{
+    /* destructor code */
+    delete mHiddenWidget;
+    delete mDrag;
+}
+
+NS_IMETHODIMP
+nsDragService::SetDropActionType( PRUint32 aActionType )
+{
+    mDropAction = Qt::IgnoreAction;
+
+    if (aActionType & DRAGDROP_ACTION_COPY)
+    {
+        mDropAction |= Qt::CopyAction;
+    }
+    if (aActionType & DRAGDROP_ACTION_MOVE)
+    {
+        mDropAction |= Qt::MoveAction;
+    }
+    if (aActionType & DRAGDROP_ACTION_LINK)
+    {
+        mDropAction |= Qt::LinkAction;
+    }
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDragService::SetupDragSession(
+                                nsISupportsArray *aTransferables,
+                                PRUint32 aActionType)
+{
+    PRUint32 itemCount = 0;
+    aTransferables->Count(&itemCount);
+    if (0 == itemCount)
+    {
+        qDebug("No items to drag?");
+        return NS_ERROR_FAILURE;
+    }
+
+    if (1 != itemCount)
+    {
+        qDebug("Dragging more than one item, cannot do (yet?)");
+        return NS_ERROR_NOT_IMPLEMENTED;
+    }
+
+    SetDropActionType(aActionType);
+
+    QMimeData *mimeData = new QMimeData;
+
+    nsCOMPtr<nsISupports> genericItem;
+    aTransferables->GetElementAt(0, getter_AddRefs(genericItem));
+    nsCOMPtr<nsITransferable> transferable(do_QueryInterface(genericItem));
+
+    if (transferable)
+    {
+        nsCOMPtr <nsISupportsArray> flavorList;
+        transferable->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
+
+        if (flavorList)
+        {
+            PRUint32 flavorCount;
+            flavorList->Count( &flavorCount );
+
+            for (PRUint32 flavor=0; flavor < flavorCount; flavor++)
+            {
+                nsCOMPtr<nsISupports> genericWrapper;
+                flavorList->GetElementAt(flavor, getter_AddRefs(genericWrapper));
+                nsCOMPtr<nsISupportsCString> currentFlavor;
+                currentFlavor = do_QueryInterface(genericWrapper);
+
+                if (currentFlavor)
+                {
+                    nsCOMPtr<nsISupports> data;
+                    PRUint32 dataLen = 0;
+                    nsXPIDLCString flavorStr;
+                    currentFlavor->ToString(getter_Copies(flavorStr));
+
+                    // Is it some flavor we think we could support?
+                    if (!strcmp(kURLMime, flavorStr.get())
+                     || !strcmp(kURLDataMime, flavorStr.get())
+                     || !strcmp(kURLDescriptionMime, flavorStr.get())
+                     || !strcmp(kHTMLMime, flavorStr.get())
+                     || !strcmp(kUnicodeMime, flavorStr.get())
+                        )
+                    {
+                        transferable->GetTransferData(flavorStr,getter_AddRefs(data),&dataLen);
+
+                        nsCOMPtr<nsISupportsString> wideString;
+                        wideString = do_QueryInterface(data);
+                        if (!wideString)
+                        {
+                            return NS_ERROR_FAILURE;
+                        }
+
+                        nsAutoString utf16string;
+                        wideString->GetData(utf16string);
+                        QByteArray ba((const char*) utf16string.get(), dataLen);
+
+                        mimeData->setData(flavorStr.get(), ba);
+                    }
+                }
+            }
+        }
+    }
+
+    mDrag = new QDrag( mHiddenWidget ); // TODO: Better drag source here?
+    mDrag->setMimeData(mimeData);
+
+    // mDrag and mimeData SHOULD NOT be destroyed. They are destroyed by QT.
+
+    return NS_OK;
+}
+
+/* void invokeDragSession (in nsIDOMNode aDOMNode, in nsISupportsArray aTransferables, in nsIScriptableRegion aRegion, in unsigned long aActionType); */
+NS_IMETHODIMP
+nsDragService::InvokeDragSession(
+                                nsIDOMNode *aDOMNode,
+                                nsISupportsArray *aTransferables,
+                                nsIScriptableRegion *aRegion,
+                                PRUint32 aActionType)
+{
+    nsBaseDragService::InvokeDragSession( 
+                                        aDOMNode,
+                                        aTransferables,
+                                        aRegion,
+                                        aActionType);
+
+    SetupDragSession( aTransferables, aActionType);
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDragService::ExecuteDrag()
+{
+    Qt::DropAction dropAction = mDrag->exec( mDropAction );
+
+    return NS_OK;
+}
+
+/* void invokeDragSessionWithImage ( nsIDOMNode DOMNode , nsISupportsArray transferableArray , nsIScriptableRegion region , PRUint32 actionType , nsIDOMNode image , PRInt32 imageX , PRInt32 imageY , nsIDOMMouseEvent dragEvent ); */
+NS_IMETHODIMP
+nsDragService::InvokeDragSessionWithImage(
+                        nsIDOMNode *aDOMNode,
+                        nsISupportsArray*aTransferables,
+                        nsIScriptableRegion* aRegion,
+                        PRUint32 aActionType,
+                        nsIDOMNode* aImage,
+                        PRInt32 aImageX,
+                        PRInt32 aImageY,
+                        nsIDOMMouseEvent* aDragEvent)
+{
+    nsBaseDragService::InvokeDragSessionWithImage(
+                                        aDOMNode, aTransferables,
+                                        aRegion, aActionType,
+                                        aImage,
+                                        aImageX, aImageY,
+                                        aDragEvent );
+
+    SetupDragSession( aTransferables, aActionType);
+
+    // Setup Image, and other stuff
+    if (aImage)
+    {
+        // Use the custom image 
+        // (aImageX,aImageY) specifies the offset "within the image where
+        // the cursor would be positioned"
+
+        // So, convert the aImage to QPixmap and X and Y to q QPoint
+        // and then:
+        // mDrag->setPixmap( pixmap ) or mDrag->setDragCursor( pixmap );
+        // mDrad->setHotSpot( point );
+        
+        // TODO: Not implemented yet as this cannot be currently tested
+        qDebug("Support for drag image not implemented");
+    }
+
+    return ExecuteDrag();
+}
+
+/* void invokeDragSessionWithSelection ( nsISelection selection , nsISupportsArray transferableArray , PRUint32 actionType , nsIDOMMouseEvent dragEvent ) */
+NS_IMETHODIMP
+nsDragService::InvokeDragSessionWithSelection(nsISelection* aSelection, nsISupportsArray* aTransferables, PRUint32 aActionType, nsIDOMMouseEvent* aDragEvent)
+{
+    nsBaseDragService::InvokeDragSessionWithSelection(
+                                        aSelection,
+                                        aTransferables,
+                                        aActionType,
+                                        aDragEvent );
+
+    SetupDragSession( aTransferables, aActionType);
+
+    // Setup selection related properties
+    // There is however nothing that needs to be set
+
+    return ExecuteDrag();
+}
+
+/* nsIDragSession getCurrentSession (); */
+NS_IMETHODIMP
+nsDragService::GetCurrentSession(nsIDragSession **_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void startDragSession (); */
+NS_IMETHODIMP
+nsDragService::StartDragSession()
+{
+    return nsBaseDragService::StartDragSession();
+}
+
+/* void endDragSession (in PRBool aDoneDrag); */
+NS_IMETHODIMP
+nsDragService::EndDragSession(PRBool aDoneDrag)
+{
+    return nsBaseDragService::EndDragSession(aDoneDrag);
+}
+
+/* void fireDragEventAtSource (in unsigned long aMsg); */
+NS_IMETHODIMP
+nsDragService::FireDragEventAtSource(PRUint32 aMsg)
+{
+    return nsBaseDragService::FireDragEventAtSource(aMsg);
+}
+
+/* TODO: What is this? */
+NS_IMETHODIMP
+nsDragService::Suppress()
+{
+    return nsBaseDragService::Suppress();
+}
+
+/* TODO: What is this? */
+NS_IMETHODIMP
+nsDragService::Unsuppress()
+{
+    return nsBaseDragService::Unsuppress();
+}
+
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsDragService.h
@@ -0,0 +1,68 @@
+/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ *   Oleg Romashin <romaxa@gmail.com>
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Oleg Romashin <romaxa@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsDragService_h__
+#define nsDragService_h__
+
+#include "nsBaseDragService.h"
+#include <qdrag.h>
+
+/* Header file */
+class nsDragService : public nsBaseDragService
+{
+public:
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIDRAGSERVICE
+
+    nsDragService();
+
+private:
+    ~nsDragService();
+
+protected:
+    /* additional members */
+    NS_IMETHODIMP SetupDragSession(nsISupportsArray *aTransferables, PRUint32 aActionType);
+    NS_IMETHODIMP SetDropActionType(PRUint32 aActionType);
+    NS_IMETHODIMP ExecuteDrag();
+
+    QDrag *mDrag;
+    Qt::DropActions mDropAction;
+    QWidget *mHiddenWidget;
+};
+
+#endif // nsDragService_h__
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsFilePicker.cpp
@@ -0,0 +1,280 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ *  Zack Rusin <zack@kde.org>.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Lars Knoll <knoll@kde.org>
+ *   Zack Rusin <zack@kde.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "nsFilePicker.h"
+
+#include "nsILocalFile.h"
+#include "nsIURI.h"
+#include "nsISupportsArray.h"
+#include "nsMemory.h"
+#include "nsEnumeratorUtils.h"
+#include "nsNetUtil.h"
+#include "nsReadableUtils.h"
+
+#include <qfile.h>
+#include <qstringlist.h>
+
+/* Implementation file */
+NS_IMPL_ISUPPORTS1(nsFilePicker, nsIFilePicker)
+
+nsFilePicker::nsFilePicker()
+    : mDialog(0),
+      mMode(nsIFilePicker::modeOpen)
+{
+    qDebug("nsFilePicker constructor");
+}
+
+nsFilePicker::~nsFilePicker()
+{
+    qDebug("nsFilePicker destructor");
+    delete mDialog;
+}
+
+NS_IMETHODIMP
+nsFilePicker::Init(nsIDOMWindow *parent, const nsAString & title, PRInt16 mode)
+{
+    qDebug("nsFilePicker::Init()");
+    return nsBaseFilePicker::Init(parent, title, mode);
+}
+
+/* void appendFilters (in long filterMask); */
+NS_IMETHODIMP
+nsFilePicker::AppendFilters(PRInt32 filterMask)
+{
+    return nsBaseFilePicker::AppendFilters(filterMask);
+}
+
+/* void appendFilter (in AString title, in AString filter); */
+NS_IMETHODIMP
+nsFilePicker::AppendFilter(const nsAString & aTitle, const nsAString & aFilter)
+{
+    if (aFilter.Equals(NS_LITERAL_STRING("..apps"))) {
+        // No platform specific thing we can do here, really....
+        return NS_OK;
+    }
+
+    nsCAutoString filter, name;
+    CopyUTF16toUTF8(aFilter, filter);
+    CopyUTF16toUTF8(aTitle, name);
+
+    mFilters.AppendCString(filter);
+    mFilterNames.AppendCString(name);
+
+    return NS_OK;
+}
+
+/* attribute AString defaultString; */
+NS_IMETHODIMP
+nsFilePicker::GetDefaultString(nsAString & aDefaultString)
+{
+    mDefault = aDefaultString;
+
+    return NS_OK;
+}
+NS_IMETHODIMP
+nsFilePicker::SetDefaultString(const nsAString & aDefaultString)
+{
+    return NS_ERROR_FAILURE;
+}
+
+/* attribute AString defaultExtension; */
+NS_IMETHODIMP
+nsFilePicker::GetDefaultExtension(nsAString & aDefaultExtension)
+{
+    aDefaultExtension = mDefaultExtension;
+
+    return NS_OK;
+}
+NS_IMETHODIMP
+nsFilePicker::SetDefaultExtension(const nsAString & aDefaultExtension)
+{
+    mDefaultExtension = aDefaultExtension;
+
+    return NS_OK;
+}
+
+/* attribute long filterIndex; */
+NS_IMETHODIMP
+nsFilePicker::GetFilterIndex(PRInt32 *aFilterIndex)
+{
+    *aFilterIndex = mSelectedType;
+
+    return NS_OK;
+}
+NS_IMETHODIMP
+nsFilePicker::SetFilterIndex(PRInt32 aFilterIndex)
+{
+    mSelectedType = aFilterIndex;
+
+    return NS_OK;
+}
+
+/* readonly attribute nsILocalFile file; */
+NS_IMETHODIMP
+nsFilePicker::GetFile(nsILocalFile * *aFile)
+{
+    NS_ENSURE_ARG_POINTER(aFile);
+
+    *aFile = nsnull;
+    if (mFile.IsEmpty()) {
+        return NS_OK;
+    }
+
+    nsCOMPtr<nsILocalFile> file(do_CreateInstance("@mozilla.org/file/local;1"));
+    NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
+
+    file->InitWithNativePath(mFile);
+
+    NS_ADDREF(*aFile = file);
+
+    return NS_OK;
+}
+
+/* readonly attribute nsIFileURL fileURL; */
+NS_IMETHODIMP
+nsFilePicker::GetFileURL(nsIURI * *aFileURL)
+{
+    nsCOMPtr<nsILocalFile> file;
+    GetFile(getter_AddRefs(file));
+
+    nsCOMPtr<nsIURI> uri;
+    NS_NewFileURI(getter_AddRefs(uri), file);
+    NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
+
+    return CallQueryInterface(uri, aFileURL);
+}
+
+/* readonly attribute nsISimpleEnumerator files; */
+NS_IMETHODIMP
+nsFilePicker::GetFiles(nsISimpleEnumerator * *aFiles)
+{
+    NS_ENSURE_ARG_POINTER(aFiles);
+
+    if (mMode == nsIFilePicker::modeOpenMultiple) {
+        return NS_NewArrayEnumerator(aFiles, mFiles);
+    }
+
+    return NS_ERROR_FAILURE;
+}
+
+/* short show (); */
+NS_IMETHODIMP
+nsFilePicker::Show(PRInt16 *aReturn)
+{
+    qDebug("nsFilePicker::Show()");
+    nsCAutoString directory;
+    if (mDisplayDirectory) {
+        mDisplayDirectory->GetNativePath(directory);
+    }
+
+    switch (mMode) {
+    case nsIFilePicker::modeOpen:
+        break;
+    case nsIFilePicker::modeOpenMultiple:
+        mDialog->setFileMode(QFileDialog::ExistingFiles);
+        break;
+    case nsIFilePicker::modeSave:
+        mDialog->setFileMode(QFileDialog::AnyFile);
+        break;
+    case nsIFilePicker::modeGetFolder:
+        mDialog->setFileMode(QFileDialog::DirectoryOnly);
+        break;
+    default:
+        break;
+    }
+
+    mDialog->selectFile(QString::fromUtf16(mDefault.get()));
+
+    mDialog->setDirectory(directory.get());
+
+    QStringList filters;
+    PRInt32 count = mFilters.Count();
+    for (PRInt32 i = 0; i < count; ++i) {
+        filters.append( mFilters[i]->get() );
+    }
+    mDialog->setFilters(filters);
+
+    switch (mDialog->exec()) {
+    case QDialog::Accepted: {
+        QStringList files = mDialog->selectedFiles();
+        QString selected;
+        if (!files.isEmpty())
+        {
+            selected = files[0];
+        }
+
+        QString path = QFile::encodeName(selected);
+        qDebug("path is '%s'", path.data());
+        mFile.Assign(path.toUtf8().data());
+        *aReturn = nsIFilePicker::returnOK;
+        if (mMode == modeSave) {
+            nsCOMPtr<nsILocalFile> file;
+            GetFile(getter_AddRefs(file));
+            if (file) {
+                PRBool exists = PR_FALSE;
+                file->Exists(&exists);
+                if (exists) {
+                    *aReturn = nsIFilePicker::returnReplace;
+                }
+            }
+        }
+    }
+        break;
+    case QDialog::Rejected: {
+        *aReturn = nsIFilePicker::returnCancel;
+    }
+        break;
+    default:
+        *aReturn = nsIFilePicker::returnCancel;
+        break;
+    }
+
+
+    return NS_OK;
+}
+
+void nsFilePicker::InitNative(nsIWidget *parent, const nsAString &title, PRInt16 mode)
+{
+    qDebug("nsFilePicker::InitNative()");
+    QWidget *parentWidget = (parent)? (QWidget*)parent->GetNativeData(NS_NATIVE_WIDGET):0;
+
+    nsAutoString str(title);
+    mDialog = new QFileDialog(parentWidget, QString::fromUtf16(str.get()));
+    mMode = mode;
+}
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsFilePicker.h
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ *  Zack Rusin <zack@kde.org>.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Lars Knoll <knoll@kde.org>
+ *   Zack Rusin <zack@kde.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef NSFILEPICKER_H
+#define NSFILEPICKER_H
+
+#include "nsBaseFilePicker.h"
+#include "nsString.h"
+#include "nsIURI.h"
+#include "nsVoidArray.h"
+#include <qfiledialog.h>
+
+class nsIWidget;
+class nsILocalFile;
+class nsISupportsArray;
+class QFileDialog;
+
+class nsFilePicker : public nsBaseFilePicker
+{
+public:
+    nsFilePicker();
+
+    NS_DECL_ISUPPORTS
+
+    // nsIFilePicker (less what's in nsBaseFilePicker)
+    NS_IMETHODIMP Init(nsIDOMWindow *parent, const nsAString & title, PRInt16 mode);
+    NS_IMETHODIMP AppendFilters(PRInt32 filterMask);
+    NS_IMETHODIMP AppendFilter(const nsAString & aTitle, const nsAString & aFilter);
+    NS_IMETHODIMP GetDefaultString(nsAString & aDefaultString);
+    NS_IMETHODIMP SetDefaultString(const nsAString & aDefaultString);
+    NS_IMETHODIMP GetDefaultExtension(nsAString & aDefaultExtension);
+    NS_IMETHODIMP SetDefaultExtension(const nsAString & aDefaultExtension);
+    NS_IMETHODIMP GetFilterIndex(PRInt32 *aFilterIndex);
+    NS_IMETHODIMP SetFilterIndex(PRInt32 aFilterIndex);
+    NS_IMETHODIMP GetFile(nsILocalFile * *aFile);
+    NS_IMETHODIMP GetFileURL(nsIURI * *aFileURL);
+    NS_IMETHODIMP GetFiles(nsISimpleEnumerator * *aFiles);
+    NS_IMETHODIMP Show(PRInt16 *aReturn);
+
+private:
+    ~nsFilePicker();
+    void InitNative(nsIWidget*, const nsAString&, short int);
+
+protected:
+    QFileDialog *mDialog;
+    nsCOMPtr<nsISupportsArray> mFiles;
+
+    PRInt16   mMode;
+    PRInt16   mSelectedType;
+    nsCString mFile;
+    nsString  mTitle;
+    nsString  mDefault;
+    nsString  mDefaultExtension;
+
+    nsCStringArray mFilters;
+    nsCStringArray mFilterNames;
+};
+
+#endif
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsIdleServiceQt.cpp
@@ -0,0 +1,160 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Gijs Kruitbosch <gijskruitbosch@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIdleServiceQt.h"
+#include "nsIServiceManager.h"
+#include "nsDebug.h"
+#include "prlink.h"
+
+
+#ifdef Q_WS_X11
+#include <QX11Info>
+
+typedef PRBool (*_XScreenSaverQueryExtension_fn)(Display* dpy, int* event_base,
+                                                 int* error_base);
+
+typedef XScreenSaverInfo* (*_XScreenSaverAllocInfo_fn)(void);
+
+typedef void (*_XScreenSaverQueryInfo_fn)(Display* dpy, Drawable drw,
+                                          XScreenSaverInfo *info);
+
+static PRBool sInitialized = PR_FALSE;
+static _XScreenSaverQueryExtension_fn _XSSQueryExtension = nsnull;
+static _XScreenSaverAllocInfo_fn _XSSAllocInfo = nsnull;
+static _XScreenSaverQueryInfo_fn _XSSQueryInfo = nsnull;
+
+
+NS_IMPL_ISUPPORTS1(nsIdleServiceQt, nsIIdleService)
+
+nsIdleServiceQt::nsIdleServiceQt()
+    : mXssInfo(nsnull)
+{
+}
+
+static void Initialize()
+{
+    sInitialized = PR_TRUE;
+
+    // This will leak - See comments in ~nsIdleServiceQt().
+    PRLibrary* xsslib = PR_LoadLibrary("libXss.so.1");
+    if (!xsslib) {
+        return;
+    }
+
+    _XSSQueryExtension = (_XScreenSaverQueryExtension_fn)
+        PR_FindFunctionSymbol(xsslib, "XScreenSaverQueryExtension");
+    _XSSAllocInfo = (_XScreenSaverAllocInfo_fn)
+        PR_FindFunctionSymbol(xsslib, "XScreenSaverAllocInfo");
+    _XSSQueryInfo = (_XScreenSaverQueryInfo_fn)
+        PR_FindFunctionSymbol(xsslib, "XScreenSaverQueryInfo");
+}
+
+nsIdleServiceQt::~nsIdleServiceQt()
+{
+    if (mXssInfo)
+        XFree(mXssInfo);
+
+// It is not safe to unload libXScrnSaver until each display is closed because
+// the library registers callbacks through XESetCloseDisplay (Bug 397607).
+// (Also the library and its functions are scoped for the file not the object.)
+#if 0
+    if (xsslib) {
+        PR_UnloadLibrary(xsslib);
+        xsslib = nsnull;
+    }
+#endif
+}
+
+NS_IMETHODIMP
+nsIdleServiceQt::GetIdleTime(PRUint32 *aTimeDiff)
+{
+    // Ask xscreensaver about idle time:
+    *aTimeDiff = 0;
+
+    // We might not have a display (cf. in xpcshell)
+    Display *dplay = QX11Info::display();
+    if (!dplay) {
+        return NS_ERROR_FAILURE;
+    }
+
+    if (!sInitialized) {
+        Initialize();
+    }
+    if (!_XSSQueryExtension || !_XSSAllocInfo || !_XSSQueryInfo) {
+        return NS_ERROR_FAILURE;
+    }
+
+    int event_base, error_base;
+    if (_XSSQueryExtension(dplay, &event_base, &error_base)) {
+        if (!mXssInfo)
+            mXssInfo = _XSSAllocInfo();
+        if (!mXssInfo)
+            return NS_ERROR_OUT_OF_MEMORY;
+
+        _XSSQueryInfo(dplay, QX11Info::appRootWindow(), mXssInfo);
+        *aTimeDiff = mXssInfo->idle;
+        return NS_OK;
+    }
+
+    return NS_ERROR_FAILURE;
+}
+
+#else
+
+NS_IMPL_ISUPPORTS1(nsIdleServiceQt, nsIIdleService)
+
+nsIdleServiceQt::nsIdleServiceQt()
+{
+}
+
+static void Initialize()
+{
+}
+
+nsIdleServiceQt::~nsIdleServiceQt()
+{
+}
+
+NS_IMETHODIMP
+nsIdleServiceQt::GetIdleTime(PRUint32 *aTimeDiff)
+{
+    return NS_ERROR_FAILURE;
+}
+
+#endif
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsIdleServiceQt.h
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Gijs Kruitbosch <gijskruitbosch@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsIdleServiceQt_h__
+#define nsIdleServiceQt_h__
+
+#include "nsIdleService.h"
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+typedef struct {
+    Window window;              // Screen saver window
+    int state;                  // ScreenSaver(Off,On,Disabled)
+    int kind;                   // ScreenSaver(Blanked,Internal,External)
+    unsigned long til_or_since; // milliseconds since/til screensaver kicks in
+    unsigned long idle;         // milliseconds idle
+    unsigned long event_mask;   // event stuff
+} XScreenSaverInfo;
+
+class nsIdleServiceQt : public nsIdleService
+{
+public:
+    NS_DECL_ISUPPORTS
+    nsIdleServiceQt();
+
+    NS_IMETHOD GetIdleTime(PRUint32* idleTime);
+private:
+    ~nsIdleServiceQt();
+    XScreenSaverInfo* mXssInfo;
+};
+
+#endif // nsIdleServiceQt_h__
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsLookAndFeel.cpp
@@ -0,0 +1,558 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Lars Knoll <knoll@kde.org>
+ *   Zack Rusin <zack@kde.org>
+ *   John C. Griggs <johng@corel.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "nsLookAndFeel.h"
+
+#include <QPalette>
+#include <QApplication>
+#include <QStyle>
+#include <qglobal.h>
+
+#undef NS_LOOKANDFEEL_DEBUG
+#ifdef NS_LOOKANDFEEL_DEBUG
+#include <QDebug>
+#endif
+
+#define QCOLOR_TO_NS_RGB(c) \
+    ((nscolor)NS_RGB(c.red(),c.green(),c.blue()))
+
+nsLookAndFeel::nsLookAndFeel() : nsXPLookAndFeel()
+{
+}
+
+nsLookAndFeel::~nsLookAndFeel()
+{
+}
+
+nsresult nsLookAndFeel::NativeGetColor(const nsColorID aID,nscolor &aColor)
+{
+  nsresult res = NS_OK;
+
+  if (!qApp)
+    return NS_ERROR_FAILURE;
+
+  QPalette palette = qApp->palette();
+
+  switch (aID) {
+    case eColor_WindowBackground:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Window));
+      break;
+
+    case eColor_WindowForeground:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Window));
+      break;
+
+    case eColor_WidgetBackground:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Window));
+      break;
+
+    case eColor_WidgetForeground:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::WindowText));
+      break;
+
+    case eColor_WidgetSelectBackground:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Window));
+      break;
+
+    case eColor_WidgetSelectForeground:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::WindowText));
+      break;
+
+    case eColor_Widget3DHighlight:
+      aColor = NS_RGB(0xa0,0xa0,0xa0);
+      break;
+
+    case eColor_Widget3DShadow:
+      aColor = NS_RGB(0x40,0x40,0x40);
+      break;
+
+    case eColor_TextBackground:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Window));
+      break;
+
+    case eColor_TextForeground:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::WindowText));
+      break;
+
+    case eColor_TextSelectBackground:
+    case eColor_IMESelectedRawTextBackground:
+    case eColor_IMESelectedConvertedTextBackground:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Highlight));
+      break;
+
+    case eColor_TextSelectForeground:
+    case eColor_IMESelectedRawTextForeground:
+    case eColor_IMESelectedConvertedTextForeground:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::HighlightedText));
+      break;
+
+    case eColor_IMERawInputBackground:
+    case eColor_IMEConvertedTextBackground:
+      aColor = NS_TRANSPARENT;
+      break;
+
+    case eColor_IMERawInputForeground:
+    case eColor_IMEConvertedTextForeground:
+      aColor = NS_SAME_AS_FOREGROUND_COLOR;
+      break;
+
+    case eColor_IMERawInputUnderline:
+    case eColor_IMEConvertedTextUnderline:
+      aColor = NS_SAME_AS_FOREGROUND_COLOR;
+      break;
+
+    case eColor_IMESelectedRawTextUnderline:
+    case eColor_IMESelectedConvertedTextUnderline:
+      aColor = NS_TRANSPARENT;
+      break;
+
+    case eColor_activeborder:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Window));
+      break;
+
+    case eColor_activecaption:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Window));
+      break;
+
+    case eColor_appworkspace:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Window));
+      break;
+
+    case eColor_background:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Window));
+      break;
+
+    case eColor_captiontext:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Text));
+      break;
+
+    case eColor_graytext:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Disabled, QPalette::Text));
+      break;
+
+    case eColor_highlight:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Highlight));
+      break;
+
+    case eColor_highlighttext:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::HighlightedText));
+      break;
+
+    case eColor_inactiveborder:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Disabled, QPalette::Window));
+      break;
+
+    case eColor_inactivecaption:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Disabled, QPalette::Window));
+      break;
+
+    case eColor_inactivecaptiontext:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Disabled, QPalette::Text));
+      break;
+
+    case eColor_infobackground:
+#if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0))
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::ToolTipBase));
+#else
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Base));
+#endif
+      break;
+
+    case eColor_infotext:
+#if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0))
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::ToolTipText));
+#else
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Text));
+#endif
+      break;
+
+    case eColor_menu:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Window));
+      break;
+
+    case eColor_menutext:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Text));
+      break;
+
+    case eColor_scrollbar:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Mid));
+      break;
+
+    case eColor_threedface:
+    case eColor_buttonface:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Button));
+      break;
+
+    case eColor_buttonhighlight:
+    case eColor_threedhighlight:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Dark));
+      break;
+
+    case eColor_buttontext:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::ButtonText));
+      break;
+
+    case eColor_buttonshadow:
+    case eColor_threedshadow:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Dark));
+      break;
+
+    case eColor_threeddarkshadow:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Shadow));
+      break;
+
+    case eColor_threedlightshadow:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Light));
+      break;
+
+    case eColor_window:
+    case eColor_windowframe:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Window));
+      break;
+
+    case eColor_windowtext:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Text));
+      break;
+
+     // from the CSS3 working draft (not yet finalized)
+     // http://www.w3.org/tr/2000/wd-css3-userint-20000216.html#color
+
+    case eColor__moz_buttondefault:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Button));
+      break;
+
+    case eColor__moz_field:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Base));
+      break;
+
+    case eColor__moz_fieldtext:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Text));
+      break;
+
+    case eColor__moz_dialog:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Window));
+      break;
+
+    case eColor__moz_dialogtext:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::WindowText));
+      break;
+
+    case eColor__moz_dragtargetzone:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Window));
+      break;
+
+    case eColor__moz_buttonhovertext:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::ButtonText));
+      break;
+
+    case eColor__moz_menuhovertext:
+    case eColor__moz_menubarhovertext:
+      aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Text));
+      break;
+
+    default:
+      aColor = 0;
+      res    = NS_ERROR_FAILURE;
+      break;
+  }
+  return res;
+}
+
+#ifdef NS_LOOKANDFEEL_DEBUG
+static const char *metricToString[] = {
+    "eMetric_WindowTitleHeight",
+    "eMetric_WindowBorderWidth",
+    "eMetric_WindowBorderHeight",
+    "eMetric_Widget3DBorder",
+    "eMetric_TextFieldBorder",
+    "eMetric_TextFieldHeight",
+    "eMetric_TextVerticalInsidePadding",
+    "eMetric_TextShouldUseVerticalInsidePadding",
+    "eMetric_TextHorizontalInsideMinimumPadding", 
+    "eMetric_TextShouldUseHorizontalInsideMinimumPadding",
+    "eMetric_ButtonHorizontalInsidePaddingNavQuirks",  
+    "eMetric_ButtonHorizontalInsidePaddingOffsetNavQuirks", 
+    "eMetric_CheckboxSize",
+    "eMetric_RadioboxSize",
+    "eMetric_ListShouldUseHorizontalInsideMinimumPadding",
+    "eMetric_ListHorizontalInsideMinimumPadding", 
+    "eMetric_ListShouldUseVerticalInsidePadding",
+    "eMetric_ListVerticalInsidePadding",
+    "eMetric_CaretBlinkTime",
+    "eMetric_CaretWidth",
+    "eMetric_ShowCaretDuringSelection",
+    "eMetric_SelectTextfieldsOnKeyFocus",
+    "eMetric_SubmenuDelay",
+    "eMetric_MenusCanOverlapOSBar",
+    "eMetric_SkipNavigatingDisabledMenuItem",
+    "eMetric_DragFullWindow",
+    "eMetric_DragThresholdX",
+    "eMetric_DragThresholdY",
+    "eMetric_UseAccessibilityTheme",
+    "eMetric_IsScreenReaderActive",
+    "eMetric_ScrollArrowStyle",
+    "eMetric_ScrollSliderStyle",
+    "eMetric_ScrollButtonLeftMouseButtonAction",
+    "eMetric_ScrollButtonMiddleMouseButtonAction",
+    "eMetric_ScrollButtonRightMouseButtonAction",
+    "eMetric_TreeOpenDelay",
+    "eMetric_TreeCloseDelay",
+    "eMetric_TreeLazyScrollDelay",
+    "eMetric_TreeScrollDelay",
+    "eMetric_TreeScrollLinesMax",
+    "eMetric_TabFocusModel",
+    "eMetric_WindowsDefaultTheme",
+    "eMetric_AlertNotificationOrigin",
+    "eMetric_ScrollToClick",
+    "eMetric_IMERawInputUnderlineStyle",
+    "eMetric_IMESelectedRawTextUnderlineStyle",
+    "eMetric_IMEConvertedTextUnderlineStyle",
+    "eMetric_IMESelectedConvertedTextUnderline",
+    "eMetric_ImagesInMenus"
+    };
+#endif
+
+NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID,PRInt32 &aMetric)
+{
+#ifdef NS_LOOKANDFEEL_DEBUG
+  qDebug("nsLookAndFeel::GetMetric aID = %s", metricToString[aID]);
+#endif
+
+  nsresult res = nsXPLookAndFeel::GetMetric(aID, aMetric);
+  if (NS_SUCCEEDED(res))
+      return res;
+
+  res = NS_OK;
+
+  QStyle* qStyle = qApp->style();
+
+  switch (aID) {
+    case eMetric_WindowTitleHeight:
+      aMetric = qStyle->pixelMetric(QStyle::PM_TitleBarHeight);
+      break;
+
+    case eMetric_WindowBorderWidth:
+      // There was once code in nsDeviceContextQt::GetSystemAttribute to
+      // use the border width obtained from a widget in its Init method.
+      break;
+
+    case eMetric_WindowBorderHeight:
+      // There was once code in nsDeviceContextQt::GetSystemAttribute to
+      // use the border width obtained from a widget in its Init method.
+      break;
+
+    case eMetric_Widget3DBorder:
+      aMetric = 4;
+      break;
+
+    case eMetric_TextFieldHeight:
+      aMetric = 15;
+      break;
+
+    case eMetric_TextFieldBorder:
+      aMetric = 2;
+      break;
+
+    case eMetric_TextVerticalInsidePadding:
+      aMetric = 0;
+      break;
+
+    case eMetric_TextShouldUseVerticalInsidePadding:
+      aMetric = 0;
+      break;
+
+    case eMetric_TextHorizontalInsideMinimumPadding:
+      aMetric = 15;
+      break;
+
+    case eMetric_TextShouldUseHorizontalInsideMinimumPadding:
+      aMetric = 1;
+      break;
+
+    case eMetric_ButtonHorizontalInsidePaddingNavQuirks:
+      aMetric = 10;
+      break;
+
+    case eMetric_ButtonHorizontalInsidePaddingOffsetNavQuirks:
+      aMetric = 8;
+      break;
+
+    case eMetric_CheckboxSize:
+    case eMetric_RadioboxSize:
+      aMetric = 15;
+      aMetric = qStyle->pixelMetric(QStyle::PM_CheckListButtonSize);
+      break;
+
+    case eMetric_ListShouldUseHorizontalInsideMinimumPadding:
+      aMetric = 15;
+      break;
+
+    case eMetric_ListHorizontalInsideMinimumPadding:
+      aMetric = 15;
+      break;
+
+    case eMetric_ListShouldUseVerticalInsidePadding:
+      aMetric = 1;
+      break;
+
+    case eMetric_ListVerticalInsidePadding:
+      aMetric = 1;
+      break;
+
+    case eMetric_CaretBlinkTime:
+      aMetric = 500;
+      break;
+
+    case eMetric_CaretWidth:
+      aMetric = 1;
+      break;
+
+    case eMetric_ShowCaretDuringSelection:
+      aMetric = 0;
+      break;
+
+    case eMetric_SelectTextfieldsOnKeyFocus:
+      // Select textfield content when focused by kbd
+      // used by nsEventStateManager::sTextfieldSelectModel
+      aMetric = 1;
+      break;
+
+    case eMetric_SubmenuDelay:
+      aMetric = 200;
+      break;
+
+    case eMetric_MenusCanOverlapOSBar:
+      // we want XUL popups to be able to overlap the task bar.
+      aMetric = 1;
+      break;
+
+    case eMetric_DragFullWindow:
+      aMetric = 1;
+      break;
+
+    case eMetric_ScrollArrowStyle:
+      aMetric = eMetric_ScrollArrowStyleSingle;
+      break;
+
+    case eMetric_ScrollSliderStyle:
+      aMetric = eMetric_ScrollThumbStyleProportional;
+      break;
+
+    case eMetric_WindowsDefaultTheme:
+      aMetric = 0;
+      res = NS_ERROR_NOT_IMPLEMENTED;
+      break;
+
+    default:
+      aMetric = 0;
+      res = NS_ERROR_FAILURE;
+  }
+  return res;
+}
+
+#ifdef NS_LOOKANDFEEL_DEBUG
+static const char *floatMetricToString[] = {
+    "eMetricFloat_TextFieldVerticalInsidePadding",
+    "eMetricFloat_TextFieldHorizontalInsidePadding",
+    "eMetricFloat_TextAreaVerticalInsidePadding",
+    "eMetricFloat_TextAreaHorizontalInsidePadding",
+    "eMetricFloat_ListVerticalInsidePadding",
+    "eMetricFloat_ListHorizontalInsidePadding",
+    "eMetricFloat_ButtonVerticalInsidePadding",
+    "eMetricFloat_ButtonHorizontalInsidePadding",
+    "eMetricFloat_IMEUnderlineRelativeSize"
+};
+#endif
+
+NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricFloatID aID,
+                                       float &aMetric)
+{
+#ifdef NS_LOOKANDFEEL_DEBUG
+  qDebug("nsLookAndFeel::GetMetric aID = %s", floatMetricToString[aID]);
+#endif
+
+  nsresult res = nsXPLookAndFeel::GetMetric(aID, aMetric);
+  if (NS_SUCCEEDED(res))
+      return res;
+  res = NS_OK;
+
+  switch (aID) {
+    case eMetricFloat_TextFieldVerticalInsidePadding:
+      aMetric = 0.25f;
+      break;
+
+    case eMetricFloat_TextFieldHorizontalInsidePadding:
+      aMetric = 0.95f; // large number on purpose so minimum padding is used
+      break;
+
+    case eMetricFloat_TextAreaVerticalInsidePadding:
+      aMetric = 0.40f;
+      break;
+
+    case eMetricFloat_TextAreaHorizontalInsidePadding:
+      aMetric = 0.40f; // large number on purpose so minimum padding is used
+      break;
+
+    case eMetricFloat_ListVerticalInsidePadding:
+      aMetric = 0.10f;
+      break;
+
+    case eMetricFloat_ListHorizontalInsidePadding:
+      aMetric = 0.40f;
+      break;
+
+    case eMetricFloat_ButtonVerticalInsidePadding:
+      aMetric = 0.25f;
+      break;
+
+    case eMetricFloat_ButtonHorizontalInsidePadding:
+      aMetric = 0.25f;
+      break;
+
+    case eMetricFloat_IMEUnderlineRelativeSize:
+      aMetric = 1.0f;
+      break;
+
+    default:
+      aMetric = -1.0;
+      res = NS_ERROR_FAILURE;
+      break;
+  }
+  return res;
+}
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsLookAndFeel.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Lars Knoll <knoll@kde.org>
+ *   John C. Griggs <johng@corel.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef __nsLookAndFeel
+#define __nsLookAndFeel
+
+#include "nsXPLookAndFeel.h"
+
+class nsLookAndFeel: public nsXPLookAndFeel
+{
+public:
+    nsLookAndFeel();
+    virtual ~nsLookAndFeel();
+
+    nsresult NativeGetColor(const nsColorID aID, nscolor &aColor);
+    NS_IMETHOD GetMetric(const nsMetricID aID, PRInt32 & aMetric);
+    NS_IMETHOD GetMetric(const nsMetricFloatID aID, float & aMetric);
+};
+
+#endif
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsNativeThemeQt.cpp
@@ -0,0 +1,641 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * David Hyatt (hyatt@netscape.com).
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Lars Knoll <knoll@kde.org>
+ *   Zack Rusin <zack@kde.org>
+ *   Tim Hill (tim@prismelite.com)
+ *   Vladimir Vukicevic <vladimir@pobox.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIFrame.h"
+
+#include <QApplication>
+#include <QStyle>
+#include <QPalette>
+#include <QRect>
+#include <QPainter>
+#include <QStyleOption>
+#include <QStyleOptionFrameV2>
+#include <QStyleOptionButton>
+#include <QFlags>
+#include <QStyleOptionComboBox>
+
+#include "nsCoord.h"
+#include "nsNativeThemeQt.h"
+#include "nsIDeviceContext.h"
+#include "nsPresContext.h"
+
+#include "nsRect.h"
+#include "nsSize.h"
+#include "nsTransform2D.h"
+#include "nsThemeConstants.h"
+#include "nsILookAndFeel.h"
+#include "nsIServiceManager.h"
+#include "nsIEventStateManager.h"
+#include "nsIDOMHTMLInputElement.h"
+#include <malloc.h>
+
+
+#include "gfxASurface.h"
+#include "gfxContext.h"
+#include "gfxQPainterSurface.h"
+#include "nsIRenderingContext.h"
+
+nsNativeThemeQt::nsNativeThemeQt()
+{
+    mNoBackgroundPalette.setColor(QPalette::Window, Qt::transparent);
+    ThemeChanged();
+}
+
+nsNativeThemeQt::~nsNativeThemeQt()
+{
+}
+
+NS_IMPL_ISUPPORTS1(nsNativeThemeQt, nsITheme)
+
+static inline QRect qRectInPixels(const nsRect &aRect,
+                                  const PRInt32 p2a)
+{
+    return QRect(NSAppUnitsToIntPixels(aRect.x, p2a),
+                 NSAppUnitsToIntPixels(aRect.y, p2a),
+                 NSAppUnitsToIntPixels(aRect.width, p2a),
+                 NSAppUnitsToIntPixels(aRect.height, p2a));
+}
+
+NS_IMETHODIMP
+nsNativeThemeQt::DrawWidgetBackground(nsIRenderingContext* aContext,
+                                      nsIFrame* aFrame,
+                                      PRUint8 aWidgetType,
+                                      const nsRect& aRect,
+                                      const nsRect& aClipRect)
+{
+    gfxContext* context = aContext->ThebesContext();
+    nsRefPtr<gfxASurface> surface = context->CurrentSurface();
+
+    context->UpdateSurfaceClip();
+
+    if (surface->GetType() != gfxASurface::SurfaceTypeQPainter)
+        return NS_ERROR_NOT_IMPLEMENTED;
+
+    gfxQPainterSurface* qSurface = (gfxQPainterSurface*) (surface.get());
+    QPainter* qPainter = qSurface->GetQPainter();
+
+    NS_ASSERTION(qPainter, "Where'd my QPainter go?");
+
+    if (qPainter == nsnull)
+        return NS_OK;
+
+    QStyle* style = qApp->style();
+
+    qPainter->save();
+
+    gfxPoint offs = surface->GetDeviceOffset();
+    qPainter->translate(offs.x, offs.y);
+
+    gfxMatrix ctm = context->CurrentMatrix();
+    if (!ctm.HasNonTranslation()) {
+        ctm.x0 = NSToCoordRound(ctm.x0);
+        ctm.y0 = NSToCoordRound(ctm.y0);
+    }
+
+    QMatrix qctm(ctm.xx, ctm.xy, ctm.yx, ctm.yy, ctm.x0, ctm.y0);
+    qPainter->setWorldMatrix(qctm, true);
+
+    PRInt32 p2a = GetAppUnitsPerDevPixel(aContext);
+
+    QRect r = qRectInPixels(aRect, p2a);
+    QRect cr = qRectInPixels(aClipRect, p2a);
+
+    QStyle::State extraFlags = QStyle::State_None;
+
+    switch (aWidgetType) {
+    case NS_THEME_RADIO:
+    case NS_THEME_RADIO_SMALL: 
+    case NS_THEME_CHECKBOX:
+    case NS_THEME_CHECKBOX_SMALL: {
+        QStyleOptionButton opt;
+        InitButtonStyle (aWidgetType, aFrame, r, opt);
+
+        if (aWidgetType == NS_THEME_CHECKBOX ||
+            aWidgetType == NS_THEME_CHECKBOX_SMALL)
+        {
+            style->drawPrimitive (QStyle::PE_IndicatorCheckBox, &opt, qPainter);
+        } else {
+            style->drawPrimitive (QStyle::PE_IndicatorRadioButton, &opt, qPainter);
+        }
+        break;
+    }
+    case NS_THEME_BUTTON:
+    case NS_THEME_BUTTON_BEVEL: {
+        QStyleOptionButton opt;
+        InitButtonStyle (aWidgetType, aFrame, r, opt);
+
+        if (aWidgetType == NS_THEME_BUTTON) {
+            style->drawPrimitive(QStyle::PE_PanelButtonCommand, &opt, qPainter);
+            if (IsDefaultButton(aFrame))
+                style->drawPrimitive(QStyle::PE_FrameDefaultButton, &opt, qPainter);
+        } else {
+            style->drawPrimitive(QStyle::PE_PanelButtonBevel, &opt, qPainter);
+            style->drawPrimitive(QStyle::PE_FrameButtonBevel, &opt, qPainter);
+        }
+        break;
+    }
+    case NS_THEME_SCROLLBAR: {
+        qPainter->fillRect(r, qApp->palette().brush(QPalette::Normal, QPalette::Window));
+        break;
+    }
+    case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL: {
+        qPainter->fillRect(r, qApp->palette().brush(QPalette::Active, QPalette::Window));
+        break;
+    }
+    case NS_THEME_SCROLLBAR_TRACK_VERTICAL: {
+        qPainter->fillRect(r, qApp->palette().brush(QPalette::Active, QPalette::Window));
+        break;
+    }
+    case NS_THEME_SCROLLBAR_BUTTON_LEFT: {
+        QStyleOptionSlider opt;
+        InitPlainStyle(aWidgetType, aFrame, r, (QStyleOption&)opt, QStyle::State_Horizontal);
+        opt.orientation = Qt::Horizontal;
+        style->drawControl(QStyle::CE_ScrollBarSubLine, &opt, qPainter, NULL);
+        break;
+        }
+    case NS_THEME_SCROLLBAR_BUTTON_RIGHT: {
+        QStyleOptionSlider opt;
+        InitPlainStyle(aWidgetType, aFrame, r, (QStyleOption&)opt, QStyle::State_Horizontal);
+        opt.orientation = Qt::Horizontal;
+        style->drawControl(QStyle::CE_ScrollBarAddLine, &opt, qPainter, NULL);
+        break;
+        }
+    case NS_THEME_SCROLLBAR_BUTTON_UP: {
+        QStyleOptionSlider opt;
+        InitPlainStyle(aWidgetType, aFrame, r, (QStyleOption&)opt);
+        opt.orientation = Qt::Vertical;
+        style->drawControl(QStyle::CE_ScrollBarSubLine, &opt, qPainter, NULL);
+        break;
+    }
+    case NS_THEME_SCROLLBAR_BUTTON_DOWN: {
+        QStyleOptionSlider opt;
+        InitPlainStyle(aWidgetType, aFrame, r, (QStyleOption&)opt);
+        opt.orientation = Qt::Vertical;
+        style->drawControl(QStyle::CE_ScrollBarAddLine, &opt, qPainter, NULL);
+        break;
+    }
+    case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL: {
+        extraFlags |= QStyle::State_Horizontal;
+        QStyleOptionSlider option;
+        InitPlainStyle(aWidgetType, aFrame, r, (QStyleOption&)option, extraFlags);
+        option.orientation = Qt::Horizontal;
+        style->drawControl(QStyle::CE_ScrollBarSlider, &option, qPainter, NULL);
+        break;
+        }
+    case NS_THEME_SCROLLBAR_THUMB_VERTICAL: {
+        QStyleOptionSlider option;
+        InitPlainStyle(aWidgetType, aFrame, r, (QStyleOption&)option, extraFlags);
+        option.orientation = Qt::Vertical;
+        style->drawControl(QStyle::CE_ScrollBarSlider, &option, qPainter, NULL);
+        break;
+    }
+    case NS_THEME_DROPDOWN: {
+        QStyleOptionComboBox comboOpt;
+        
+        InitComboStyle(aWidgetType, aFrame, r, comboOpt);
+
+        style->drawComplexControl(QStyle::CC_ComboBox, &comboOpt, qPainter);
+        break;
+    }
+    case NS_THEME_DROPDOWN_BUTTON:
+        break;
+    case NS_THEME_DROPDOWN_TEXT:
+    case NS_THEME_DROPDOWN_TEXTFIELD:
+        break;
+    case NS_THEME_TEXTFIELD:
+    case NS_THEME_TEXTFIELD_MULTILINE:
+    case NS_THEME_LISTBOX: {
+        QStyleOptionFrameV2 frameOpt;
+        
+        if (!IsDisabled(aFrame))
+            frameOpt.state |= QStyle::State_Enabled;
+
+        frameOpt.rect = r;
+        frameOpt.features = QStyleOptionFrameV2::Flat;
+
+        if (aWidgetType == NS_THEME_TEXTFIELD || aWidgetType == NS_THEME_TEXTFIELD_MULTILINE) {
+            QRect contentRect = style->subElementRect(QStyle::SE_LineEditContents, &frameOpt);
+            contentRect.adjust(mFrameWidth, mFrameWidth, -mFrameWidth, -mFrameWidth);
+            qPainter->fillRect(contentRect, QBrush(Qt::white));
+        }
+        
+        frameOpt.palette = mNoBackgroundPalette;
+        style->drawPrimitive(QStyle::PE_FrameLineEdit, &frameOpt, qPainter, NULL);
+        break;
+    }
+    default:
+        break;
+    }
+
+    qPainter->restore();
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNativeThemeQt::GetWidgetBorder(nsIDeviceContext* aContext,
+                                 nsIFrame* aFrame,
+                                 PRUint8 aWidgetType,
+                                 nsMargin* aResult)
+{
+    (*aResult).top = (*aResult).bottom = (*aResult).left = (*aResult).right = 0;
+
+//     switch(aWidgetType) {
+//     case NS_THEME_TEXTFIELD:
+//     case NS_THEME_LISTBOX:
+//         (*aResult).top = (*aResult).bottom = (*aResult).left = (*aResult).right =
+//                          frameWidth;
+//     }
+
+    return NS_OK;
+}
+
+PRBool
+nsNativeThemeQt::GetWidgetPadding(nsIDeviceContext* ,
+                                  nsIFrame*, PRUint8 aWidgetType,
+                                  nsMargin* aResult)
+{
+    // XXX: Where to get padding values, framewidth?
+    if (aWidgetType == NS_THEME_TEXTFIELD ||
+        aWidgetType == NS_THEME_TEXTFIELD_MULTILINE ||
+        aWidgetType == NS_THEME_DROPDOWN) {
+        aResult->SizeTo(2, 2, 2, 2);
+        return PR_TRUE;
+    }
+
+    return PR_FALSE;
+}
+
+NS_IMETHODIMP
+nsNativeThemeQt::GetMinimumWidgetSize(nsIRenderingContext* aContext, nsIFrame* aFrame,
+                                      PRUint8 aWidgetType,
+                                      nsSize* aResult, PRBool* aIsOverridable)
+{
+    (*aResult).width = (*aResult).height = 0;
+    *aIsOverridable = PR_TRUE;
+
+    QStyle *s = qApp->style();
+
+    PRInt32 p2a = GetAppUnitsPerDevPixel(aContext);
+
+    switch (aWidgetType) {
+    case NS_THEME_RADIO_SMALL:
+    case NS_THEME_RADIO:
+    case NS_THEME_CHECKBOX_SMALL:
+    case NS_THEME_CHECKBOX: {
+        nsRect frameRect = aFrame->GetRect();
+
+        QRect qRect = qRectInPixels(frameRect, p2a);
+
+        QStyleOptionButton option;
+
+        InitButtonStyle(aWidgetType, aFrame, qRect, option);
+
+        QRect rect = s->subElementRect(
+            (aWidgetType == NS_THEME_CHECKBOX || aWidgetType == NS_THEME_CHECKBOX_SMALL ) ?
+                QStyle::SE_CheckBoxIndicator :
+                QStyle::SE_RadioButtonIndicator,
+            &option,
+            NULL);
+
+        (*aResult).width = rect.width();
+        (*aResult).height = rect.height();
+        break;
+    }
+    case NS_THEME_BUTTON: {
+        nsRect frameRect = aFrame->GetRect();
+
+        QRect qRect = qRectInPixels(frameRect, p2a);
+
+        QStyleOptionButton option;
+
+        InitButtonStyle(aWidgetType, aFrame, qRect, option);
+
+        QRect rect = s->subElementRect(
+            QStyle::SE_PushButtonFocusRect,
+            &option,
+            NULL);
+
+        (*aResult).width = rect.width();
+        (*aResult).height = rect.height();
+        break;
+    }
+    case NS_THEME_SCROLLBAR_BUTTON_UP:
+    case NS_THEME_SCROLLBAR_BUTTON_DOWN: {
+        (*aResult).width = s->pixelMetric(QStyle::PM_ScrollBarExtent);
+        (*aResult).height = (*aResult).width;
+        //*aIsOverridable = PR_FALSE;
+        break;
+    }
+    case NS_THEME_SCROLLBAR_BUTTON_LEFT:
+    case NS_THEME_SCROLLBAR_BUTTON_RIGHT: {
+        (*aResult).height = s->pixelMetric(QStyle::PM_ScrollBarExtent);
+        (*aResult).width = (*aResult).height;
+        //*aIsOverridable = PR_FALSE;
+        break;
+        }
+    case NS_THEME_SCROLLBAR_THUMB_VERTICAL: {
+        (*aResult).width = s->pixelMetric(QStyle::PM_ScrollBarExtent);
+        (*aResult).height = s->pixelMetric(QStyle::PM_ScrollBarSliderMin);
+        //*aIsOverridable = PR_FALSE;
+        break;
+        }
+    case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL: {
+        (*aResult).width = s->pixelMetric(QStyle::PM_ScrollBarSliderMin);
+        (*aResult).height = s->pixelMetric(QStyle::PM_ScrollBarExtent);
+        //*aIsOverridable = PR_FALSE;
+        break;
+        }
+    case NS_THEME_SCROLLBAR_TRACK_VERTICAL: {
+        (*aResult).width = s->pixelMetric(QStyle::PM_ScrollBarExtent);
+        (*aResult).height = s->pixelMetric(QStyle::PM_SliderLength);
+        break;
+        }
+    case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL: {
+        (*aResult).width = s->pixelMetric(QStyle::PM_SliderLength);
+        (*aResult).height = s->pixelMetric(QStyle::PM_ScrollBarExtent);
+        break;
+        }
+    case NS_THEME_DROPDOWN_BUTTON: {
+        QStyleOptionComboBox comboOpt;
+        
+        nsRect frameRect = aFrame->GetRect();
+        QRect qRect = qRectInPixels(frameRect, p2a);
+        comboOpt.rect = qRect;
+
+        InitComboStyle(aWidgetType, aFrame, qRect, comboOpt);
+
+        QRect subRect = s->subControlRect(QStyle::CC_ComboBox, &comboOpt, QStyle::SC_ComboBoxArrow, NULL);
+  
+        (*aResult).width = subRect.width();
+        (*aResult).height = subRect.height();
+        //*aIsOverridable = PR_FALSE;
+        break;
+    }
+    case NS_THEME_DROPDOWN: {
+        QStyleOptionComboBox comboOpt;
+
+        nsRect frameRect = aFrame->GetRect();
+        QRect qRect = qRectInPixels(frameRect, p2a);
+        comboOpt.rect = qRect;
+
+        InitComboStyle(aWidgetType, aFrame, qRect, comboOpt);
+
+        QRect subRect = s->subControlRect(QStyle::CC_ComboBox, 
+                                          &comboOpt, 
+                                          QStyle::SC_ComboBoxFrame, 
+                                          NULL);
+
+        (*aResult).width = subRect.width();
+        (*aResult).height = subRect.height();
+        //*aIsOverridable = PR_FALSE;
+        break;
+    }
+    case NS_THEME_DROPDOWN_TEXT: {
+        QStyleOptionComboBox comboOpt;
+        
+        nsRect frameRect = aFrame->GetRect();
+
+        QRect qRect = qRectInPixels(frameRect, p2a);
+        
+        comboOpt.rect = qRect;
+
+        QRect subRect = s->subControlRect(QStyle::CC_ComboBox, &comboOpt, QStyle::SC_ComboBoxEditField, NULL);
+       
+        (*aResult).width = subRect.width();
+        (*aResult).height = subRect.height();
+        //*aIsOverridable = PR_FALSE;
+        break;
+    }
+    case NS_THEME_DROPDOWN_TEXTFIELD: {
+        QStyleOptionComboBox comboOpt;
+        
+        nsRect frameRect = aFrame->GetRect();
+
+        QRect qRect = qRectInPixels(frameRect, p2a);
+
+        comboOpt.rect = qRect;
+
+        QRect subRect = s->subControlRect(QStyle::CC_ComboBox, &comboOpt, QStyle::SC_ComboBoxArrow, NULL);
+        QRect subRect2 = s->subControlRect(QStyle::CC_ComboBox, &comboOpt, QStyle::SC_ComboBoxFrame, NULL);
+
+        (*aResult).width = subRect.width() + subRect2.width();
+        (*aResult).height = std::max(subRect.height(), subRect2.height());
+        //*aIsOverridable = PR_FALSE;
+        break;
+    }
+    case NS_THEME_TEXTFIELD:
+    case NS_THEME_TEXTFIELD_MULTILINE:
+        break;
+    }
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNativeThemeQt::WidgetStateChanged(nsIFrame* aFrame, PRUint8 aWidgetType,
+                                    nsIAtom* aAttribute, PRBool* aShouldRepaint)
+{
+    *aShouldRepaint = TRUE;
+    return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsNativeThemeQt::ThemeChanged()
+{
+    QStyle *s = qApp->style();
+    if (s)
+      mFrameWidth = s->pixelMetric(QStyle::PM_DefaultFrameWidth);
+    return NS_OK;
+}
+
+PRBool
+nsNativeThemeQt::ThemeSupportsWidget(nsPresContext* aPresContext,
+                                     nsIFrame* aFrame,
+                                     PRUint8 aWidgetType)
+{
+    switch (aWidgetType) {
+    case NS_THEME_SCROLLBAR:
+    case NS_THEME_SCROLLBAR_BUTTON_UP:
+    case NS_THEME_SCROLLBAR_BUTTON_DOWN:
+    case NS_THEME_SCROLLBAR_BUTTON_LEFT:
+    case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
+    case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
+    case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
+    //case NS_THEME_SCROLLBAR_GRIPPER_HORIZONTAL:
+    //case NS_THEME_SCROLLBAR_GRIPPER_VERTICAL:
+    case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
+    case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
+    case NS_THEME_RADIO:
+    case NS_THEME_RADIO_SMALL:
+    case NS_THEME_CHECKBOX:
+    case NS_THEME_CHECKBOX_SMALL:
+    case NS_THEME_BUTTON_BEVEL:
+    case NS_THEME_BUTTON:
+    case NS_THEME_DROPDOWN:
+    case NS_THEME_DROPDOWN_BUTTON:
+    case NS_THEME_DROPDOWN_TEXT:
+    case NS_THEME_DROPDOWN_TEXTFIELD:
+    case NS_THEME_TEXTFIELD:
+    case NS_THEME_TEXTFIELD_MULTILINE:
+    case NS_THEME_LISTBOX:
+        return !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
+    default:
+        break;
+    }
+    return PR_FALSE;
+}
+
+PRBool
+nsNativeThemeQt::WidgetIsContainer(PRUint8 aWidgetType)
+{
+//     if (aWidgetType == NS_THEME_DROPDOWN_BUTTON ||
+//         aWidgetType == NS_THEME_RADIO ||
+//         aWidgetType == NS_THEME_CHECKBOX) {
+//         return PR_FALSE;
+//     }
+
+   return PR_TRUE;
+}
+
+PRBool
+nsNativeThemeQt::ThemeDrawsFocusForWidget(nsPresContext* aPresContext, nsIFrame* aFrame, PRUint8 aWidgetType)
+{
+    if (aWidgetType == NS_THEME_DROPDOWN ||
+        aWidgetType == NS_THEME_BUTTON || 
+        aWidgetType == NS_THEME_TREEVIEW_HEADER_CELL) { 
+        return PR_TRUE;
+    }
+
+    return PR_FALSE;
+}
+
+PRBool
+nsNativeThemeQt::ThemeNeedsComboboxDropmarker()
+{
+    return PR_TRUE;
+}
+
+void
+nsNativeThemeQt::InitButtonStyle(PRUint8 aWidgetType,
+                                 nsIFrame* aFrame,
+                                 QRect rect,
+                                 QStyleOptionButton &opt)
+{
+    PRInt32 eventState = GetContentState(aFrame, aWidgetType);
+
+    opt.rect = rect;
+    opt.palette = mNoBackgroundPalette;
+
+    PRBool disabled = IsDisabled(aFrame);
+
+    if (!disabled)
+        opt.state |= QStyle::State_Enabled;
+    if (eventState & NS_EVENT_STATE_HOVER)
+        opt.state |= QStyle::State_MouseOver;
+    if (eventState & NS_EVENT_STATE_FOCUS)
+        opt.state |= QStyle::State_HasFocus;
+    if (!disabled && eventState & NS_EVENT_STATE_ACTIVE)
+        // Don't allow sunken when disabled
+        opt.state |= QStyle::State_Sunken;
+
+    switch (aWidgetType) {
+    case NS_THEME_RADIO:
+    case NS_THEME_RADIO_SMALL:
+    case NS_THEME_CHECKBOX:
+    case NS_THEME_CHECKBOX_SMALL:
+        if (IsChecked(aFrame))
+            opt.state |= QStyle::State_On;
+        else
+            opt.state |= QStyle::State_Off;
+
+        break;
+    default:
+        if (!(eventState & NS_EVENT_STATE_ACTIVE))
+            opt.state |= QStyle::State_Raised;
+        break;
+    }
+}
+
+void
+nsNativeThemeQt::InitPlainStyle(PRUint8 aWidgetType,
+                                nsIFrame* aFrame,
+                                QRect rect,
+                                QStyleOption &opt,
+                                QStyle::State extraFlags)
+{
+    PRInt32 eventState = GetContentState(aFrame, aWidgetType);
+
+    opt.rect = rect;
+
+    if (!IsDisabled(aFrame))
+        opt.state |= QStyle::State_Enabled;
+    if (eventState & NS_EVENT_STATE_HOVER)
+        opt.state |= QStyle::State_MouseOver;
+    if (eventState & NS_EVENT_STATE_FOCUS)
+        opt.state |= QStyle::State_HasFocus;
+
+    opt.state |= extraFlags;
+}
+
+void
+nsNativeThemeQt::InitComboStyle(PRUint8 aWidgetType,
+                                nsIFrame* aFrame,
+                                QRect rect,
+                                QStyleOptionComboBox &opt)
+{
+    PRInt32 eventState = GetContentState(aFrame, aWidgetType);
+
+    PRBool disabled = IsDisabled(aFrame);
+
+    if (!disabled)
+        opt.state |= QStyle::State_Enabled;
+    if (eventState & NS_EVENT_STATE_HOVER)
+        opt.state |= QStyle::State_MouseOver;
+    if (eventState & NS_EVENT_STATE_FOCUS)
+        opt.state |= QStyle::State_HasFocus;
+    if (!(eventState & NS_EVENT_STATE_ACTIVE))
+        opt.state |= QStyle::State_Raised;
+    if (!disabled && eventState & NS_EVENT_STATE_ACTIVE)
+        // Don't allow sunken when disabled
+        opt.state |= QStyle::State_Sunken;
+
+    opt.rect = rect;
+    opt.palette = mNoBackgroundPalette;
+}
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsNativeThemeQt.h
@@ -0,0 +1,135 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Lars Knoll <knoll@kde.org>
+ *   Zack Rusin <zack@kde.org>
+ *   Tim Hill (tim@prismelite.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <QStyle>
+#include <QPalette>
+
+#include "nsITheme.h"
+#include "nsCOMPtr.h"
+#include "nsIAtom.h"
+#include "nsNativeTheme.h"
+#include "nsIDeviceContext.h"
+
+class QComboBox;
+class QStyleOptionButton;
+class QStyleOptionFrameV2;
+class QStyleOptionComboBox;
+class QRect;
+class nsIFrame;
+
+class nsNativeThemeQt : private nsNativeTheme,
+                        public nsITheme
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  // The nsITheme interface.
+  NS_IMETHOD DrawWidgetBackground(nsIRenderingContext* aContext,
+                                  nsIFrame* aFrame,
+                                  PRUint8 aWidgetType,
+                                  const nsRect& aRect,
+                                  const nsRect& aClipRect);
+
+  NS_IMETHOD GetWidgetBorder(nsIDeviceContext* aContext,
+                             nsIFrame* aFrame,
+                             PRUint8 aWidgetType,
+                             nsMargin* aResult);
+
+  NS_IMETHOD GetMinimumWidgetSize(nsIRenderingContext* aContext, nsIFrame* aFrame,
+                                  PRUint8 aWidgetType,
+                                  nsSize* aResult,
+                                  PRBool* aIsOverridable);
+
+  NS_IMETHOD WidgetStateChanged(nsIFrame* aFrame, PRUint8 aWidgetType,
+                                nsIAtom* aAttribute, PRBool* aShouldRepaint);
+
+  NS_IMETHOD ThemeChanged();
+
+  PRBool ThemeSupportsWidget(nsPresContext* aPresContext,
+                             nsIFrame* aFrame,
+                             PRUint8 aWidgetType);
+
+  PRBool WidgetIsContainer(PRUint8 aWidgetType);
+
+  virtual NS_HIDDEN_(PRBool) GetWidgetPadding(nsIDeviceContext* aContext,
+                                              nsIFrame* aFrame,
+                                              PRUint8 aWidgetType,
+                                              nsMargin* aResult);
+
+  NS_IMETHOD_(PRBool) ThemeDrawsFocusForWidget(nsPresContext* aPresContext,
+                                               nsIFrame* aFrame, PRUint8 aWidgetType);
+
+  PRBool ThemeNeedsComboboxDropmarker();
+
+  nsNativeThemeQt();
+  virtual ~nsNativeThemeQt();
+
+private:
+
+  inline PRInt32 GetAppUnitsPerDevPixel(nsIRenderingContext* aContext){
+    nsCOMPtr<nsIDeviceContext> dctx = nsnull;
+    aContext->GetDeviceContext(*getter_AddRefs(dctx));
+    return dctx->AppUnitsPerDevPixel();
+  }
+
+  void InitButtonStyle(PRUint8 widgetType,
+                       nsIFrame* aFrame,
+                       QRect rect,
+                       QStyleOptionButton &opt);
+
+  void InitPlainStyle(PRUint8 aWidgetType,
+                      nsIFrame* aFrame,
+                      QRect rect,
+                      QStyleOption &opt,
+                      QStyle::State extraFlags = QStyle::State_None);
+
+  void InitComboStyle(PRUint8 aWidgetType,
+                      nsIFrame* aFrame,
+                      QRect rect,
+                      QStyleOptionComboBox &opt);
+
+private:
+
+  PRInt32 mFrameWidth;
+
+  QPalette mNoBackgroundPalette;
+};
+
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsQtKeyUtils.cpp
@@ -0,0 +1,339 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ *  Zack Rusin <zack@kde.org>.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Lars Knoll <knoll@kde.org>
+ *   Zack Rusin <zack@kde.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "nsWindow.h"
+#include "nsQtKeyUtils.h"
+#include "keysym2ucs.h"
+
+#include "nsGUIEvent.h"
+
+struct nsKeyConverter
+{
+    int vkCode; // Platform independent key code
+    int keysym; // Qt key code
+};
+
+static struct nsKeyConverter nsKeycodes[] =
+{
+//  { NS_VK_CANCEL,        Qt::Key_Cancel },
+    { NS_VK_BACK,          Qt::Key_Backspace },
+    { NS_VK_TAB,           Qt::Key_Tab },
+//  { NS_VK_CLEAR,         Qt::Key_Clear },
+    { NS_VK_RETURN,        Qt::Key_Return },
+    { NS_VK_RETURN,        Qt::Key_Enter },
+    { NS_VK_SHIFT,         Qt::Key_Shift },
+    { NS_VK_CONTROL,       Qt::Key_Control },
+    { NS_VK_ALT,           Qt::Key_Alt },
+    { NS_VK_PAUSE,         Qt::Key_Pause },
+    { NS_VK_CAPS_LOCK,     Qt::Key_CapsLock },
+    { NS_VK_ESCAPE,        Qt::Key_Escape },
+    { NS_VK_SPACE,         Qt::Key_Space },
+    { NS_VK_PAGE_UP,       Qt::Key_PageUp },
+    { NS_VK_PAGE_DOWN,     Qt::Key_PageDown },
+    { NS_VK_END,           Qt::Key_End },
+    { NS_VK_HOME,          Qt::Key_Home },
+    { NS_VK_LEFT,          Qt::Key_Left },
+    { NS_VK_UP,            Qt::Key_Up },
+    { NS_VK_RIGHT,         Qt::Key_Right },
+    { NS_VK_DOWN,          Qt::Key_Down },
+    { NS_VK_PRINTSCREEN,   Qt::Key_Print },
+    { NS_VK_INSERT,        Qt::Key_Insert },
+    { NS_VK_DELETE,        Qt::Key_Delete },
+
+    { NS_VK_0,             Qt::Key_0 },
+    { NS_VK_1,             Qt::Key_1 },
+    { NS_VK_2,             Qt::Key_2 },
+    { NS_VK_3,             Qt::Key_3 },
+    { NS_VK_4,             Qt::Key_4 },
+    { NS_VK_5,             Qt::Key_5 },
+    { NS_VK_6,             Qt::Key_6 },
+    { NS_VK_7,             Qt::Key_7 },
+    { NS_VK_8,             Qt::Key_8 },
+    { NS_VK_9,             Qt::Key_9 },
+
+    { NS_VK_SEMICOLON,     Qt::Key_Semicolon },
+    { NS_VK_EQUALS,        Qt::Key_Equal },
+
+    { NS_VK_A,             Qt::Key_A },
+    { NS_VK_B,             Qt::Key_B },
+    { NS_VK_C,             Qt::Key_C },
+    { NS_VK_D,             Qt::Key_D },
+    { NS_VK_E,             Qt::Key_E },
+    { NS_VK_F,             Qt::Key_F },
+    { NS_VK_G,             Qt::Key_G },
+    { NS_VK_H,             Qt::Key_H },
+    { NS_VK_I,             Qt::Key_I },
+    { NS_VK_J,             Qt::Key_J },
+    { NS_VK_K,             Qt::Key_K },
+    { NS_VK_L,             Qt::Key_L },
+    { NS_VK_M,             Qt::Key_M },
+    { NS_VK_N,             Qt::Key_N },
+    { NS_VK_O,             Qt::Key_O },
+    { NS_VK_P,             Qt::Key_P },
+    { NS_VK_Q,             Qt::Key_Q },
+    { NS_VK_R,             Qt::Key_R },
+    { NS_VK_S,             Qt::Key_S },
+    { NS_VK_T,             Qt::Key_T },
+    { NS_VK_U,             Qt::Key_U },
+    { NS_VK_V,             Qt::Key_V },
+    { NS_VK_W,             Qt::Key_W },
+    { NS_VK_X,             Qt::Key_X },
+    { NS_VK_Y,             Qt::Key_Y },
+    { NS_VK_Z,             Qt::Key_Z },
+
+    { NS_VK_NUMPAD0,       Qt::Key_0 },
+    { NS_VK_NUMPAD1,       Qt::Key_1 },
+    { NS_VK_NUMPAD2,       Qt::Key_2 },
+    { NS_VK_NUMPAD3,       Qt::Key_3 },
+    { NS_VK_NUMPAD4,       Qt::Key_4 },
+    { NS_VK_NUMPAD5,       Qt::Key_5 },
+    { NS_VK_NUMPAD6,       Qt::Key_6 },
+    { NS_VK_NUMPAD7,       Qt::Key_7 },
+    { NS_VK_NUMPAD8,       Qt::Key_8 },
+    { NS_VK_NUMPAD9,       Qt::Key_9 },
+    { NS_VK_MULTIPLY,      Qt::Key_Asterisk },
+    { NS_VK_ADD,           Qt::Key_Plus },
+//  { NS_VK_SEPARATOR,     Qt::Key_Separator },
+    { NS_VK_SUBTRACT,      Qt::Key_Minus },
+    { NS_VK_DECIMAL,       Qt::Key_Period },
+    { NS_VK_DIVIDE,        Qt::Key_Slash },
+    { NS_VK_F1,            Qt::Key_F1 },
+    { NS_VK_F2,            Qt::Key_F2 },
+    { NS_VK_F3,            Qt::Key_F3 },
+    { NS_VK_F4,            Qt::Key_F4 },
+    { NS_VK_F5,            Qt::Key_F5 },
+    { NS_VK_F6,            Qt::Key_F6 },
+    { NS_VK_F7,            Qt::Key_F7 },
+    { NS_VK_F8,            Qt::Key_F8 },
+    { NS_VK_F9,            Qt::Key_F9 },
+    { NS_VK_F10,           Qt::Key_F10 },
+    { NS_VK_F11,           Qt::Key_F11 },
+    { NS_VK_F12,           Qt::Key_F12 },
+    { NS_VK_F13,           Qt::Key_F13 },
+    { NS_VK_F14,           Qt::Key_F14 },
+    { NS_VK_F15,           Qt::Key_F15 },
+    { NS_VK_F16,           Qt::Key_F16 },
+    { NS_VK_F17,           Qt::Key_F17 },
+    { NS_VK_F18,           Qt::Key_F18 },
+    { NS_VK_F19,           Qt::Key_F19 },
+    { NS_VK_F20,           Qt::Key_F20 },
+    { NS_VK_F21,           Qt::Key_F21 },
+    { NS_VK_F22,           Qt::Key_F22 },
+    { NS_VK_F23,           Qt::Key_F23 },
+    { NS_VK_F24,           Qt::Key_F24 },
+
+    { NS_VK_NUM_LOCK,      Qt::Key_NumLock },
+    { NS_VK_SCROLL_LOCK,   Qt::Key_ScrollLock },
+
+    { NS_VK_COMMA,         Qt::Key_Comma },
+    { NS_VK_PERIOD,        Qt::Key_Period },
+    { NS_VK_SLASH,         Qt::Key_Slash },
+    { NS_VK_BACK_QUOTE,    Qt::Key_QuoteLeft },
+    { NS_VK_OPEN_BRACKET,  Qt::Key_ParenLeft },
+    { NS_VK_CLOSE_BRACKET, Qt::Key_ParenRight },
+    { NS_VK_QUOTE,         Qt::Key_QuoteDbl },
+
+    { NS_VK_META,          Qt::Key_Meta }
+};
+
+
+#define IS_XSUN_XSERVER(dpy) \
+    (strstr(XServerVendor(dpy), "Sun Microsystems") != NULL)
+
+// map Sun Keyboard special keysyms on to NS_VK keys
+struct nsKeyConverter nsSunKeycodes[] = {
+    {NS_VK_ESCAPE, Qt::Key_F11 }, //bug 57262, Sun Stop key generates F11 keysym
+    {NS_VK_F1, Qt::Key_Help }, //Mapping Help key to F1
+    {NS_VK_F11, 0x1005ff10 }, //Sun F11 key generates SunF36(0x1005ff10) keysym
+    {NS_VK_F12, 0x1005ff11 }, //Sun F12 key generates SunF37(0x1005ff11) keysym
+    {NS_VK_PAGE_UP,    Qt::Key_F29 }, //KP_Prior
+    {NS_VK_PAGE_DOWN,  Qt::Key_F35 }, //KP_Next
+    {NS_VK_HOME,       Qt::Key_F27 }, //KP_Home
+    {NS_VK_END,        Qt::Key_F33 }, //KP_End
+};
+
+int
+QtKeyCodeToDOMKeyCode(int aKeysym)
+{
+    int i, length = 0;
+
+    // First, try to handle alphanumeric input, not listed in nsKeycodes:
+    // most likely, more letters will be getting typed in than things in
+    // the key list, so we will look through these first.
+
+    // since X has different key symbols for upper and lowercase letters and
+    // mozilla does not, convert gdk's to mozilla's
+    if (aKeysym >= Qt::Key_A && aKeysym <= Qt::Key_Z)
+        return aKeysym - Qt::Key_A + NS_VK_A;
+
+    // numbers
+    if (aKeysym >= Qt::Key_0 && aKeysym <= Qt::Key_9)
+        return aKeysym - Qt::Key_0 + NS_VK_0;
+
+    // keypad numbers
+//    if (aKeysym >= Qt::Key_KP_0 && aKeysym <= Qt::Key_KP_9)
+//        return aKeysym - Qt::Key_KP_0 + NS_VK_NUMPAD0;
+
+    // map Sun Keyboard special keysyms
+//    if (IS_XSUN_XSERVER(Qt::Key_DISPLAY())) {
+//        length = sizeof(nsSunKeycodes) / sizeof(struct nsKeyConverter);
+//        for (i = 0; i < length; i++) {
+//            if (nsSunKeycodes[i].keysym == aKeysym)
+//                return(nsSunKeycodes[i].vkCode);
+//        }
+//    }
+
+    // misc other things
+    length = sizeof(nsKeycodes) / sizeof(struct nsKeyConverter);
+    for (i = 0; i < length; i++) {
+        if (nsKeycodes[i].keysym == aKeysym)
+            return(nsKeycodes[i].vkCode);
+    }
+
+    // function keys
+    if (aKeysym >= Qt::Key_F1 && aKeysym <= Qt::Key_F24)
+        return aKeysym - Qt::Key_F1 + NS_VK_F1;
+
+    return((int)0);
+}
+
+int
+DOMKeyCodeToQtKeyCode(int aKeysym)
+{
+    int i, length = 0;
+
+    // First, try to handle alphanumeric input, not listed in nsKeycodes:
+    // most likely, more letters will be getting typed in than things in
+    // the key list, so we will look through these first.
+
+    if (aKeysym >= NS_VK_A && aKeysym <= NS_VK_Z)
+      // gdk and DOM both use the ASCII codes for these keys.
+      return aKeysym;
+
+    // numbers
+    if (aKeysym >= NS_VK_0 && aKeysym <= NS_VK_9)
+      // gdk and DOM both use the ASCII codes for these keys.
+      return aKeysym - Qt::Key_0 + NS_VK_0;
+
+    // keypad numbers
+    if (aKeysym >= NS_VK_NUMPAD0 && aKeysym <= NS_VK_NUMPAD9) {
+      qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
+      //return aKeysym - NS_VK_NUMPAD0 + Qt::Key_KP_0;
+      return 0;
+    }
+
+    // misc other things
+    length = NS_ARRAY_LENGTH(nsKeycodes);
+    for (i = 0; i < length; ++i) {
+      if (nsKeycodes[i].vkCode == aKeysym) {
+        return nsKeycodes[i].keysym;
+      }
+    }
+
+    // function keys
+    if (aKeysym >= NS_VK_F1 && aKeysym <= NS_VK_F9)
+      return aKeysym - NS_VK_F1 + Qt::Key_F1;
+
+    return 0;
+}
+
+// Convert gdk key event keyvals to char codes if printable, 0 otherwise
+PRUint32 nsConvertCharCodeToUnicode(QKeyEvent* aEvent)
+{
+    // Anything above 0xf000 is considered a non-printable
+    // Exception: directly encoded UCS characters
+    if (aEvent->key() > 0xf000 && (aEvent->key() & 0xff000000) != 0x01000000) {
+
+        // Keypad keys are an exception: they return a value different
+        // from their non-keypad equivalents, but mozilla doesn't distinguish.
+/*
+        switch (aEvent->key())
+            {
+            case Qt::Key_KP_Space:
+                return ' ';
+            case Qt::Key_KP_Equal:
+                return '=';
+            case Qt::Key_KP_Multiply:
+                return '*';
+            case Qt::Key_KP_Add:
+                return '+';
+            case Qt::Key_KP_Separator:
+                return ',';
+            case Qt::Key_KP_Subtract:
+                return '-';
+            case Qt::Key_KP_Decimal:
+                return '.';
+            case Qt::Key_KP_Divide:
+                return '/';
+            case Qt::Key_KP_0:
+                return '0';
+            case Qt::Key_KP_1:
+                return '1';
+            case Qt::Key_KP_2:
+                return '2';
+            case Qt::Key_KP_3:
+                return '3';
+            case Qt::Key_KP_4:
+                return '4';
+            case Qt::Key_KP_5:
+                return '5';
+            case Qt::Key_KP_6:
+                return '6';
+            case Qt::Key_KP_7:
+                return '7';
+            case Qt::Key_KP_8:
+                return '8';
+            case Qt::Key_KP_9:
+                return '9';
+            }
+
+        // non-printables
+        return 0;
+*/
+    }
+
+
+    // we're supposedly printable, let's try to convert
+    long ucs = keysym2ucs(aEvent->key());
+    if ((ucs != -1) && (ucs < 0x10000))
+        return ucs;
+
+    // I guess we couldn't convert
+    return 0;
+}
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsQtKeyUtils.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Christopher Blizzard
+ * <blizzard@mozilla.org>.  Portions created by the Initial Developer
+ * are Copyright (C) 2001 the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __nsQtKeyUtils_h__
+#define __nsQtKeyUtils_h__
+
+int      QtKeyCodeToDOMKeyCode     (int aKeysym);
+int      DOMKeyCodeToQtKeyCode     (int aKeysym);
+PRUint32 nsConvertCharCodeToUnicode (QKeyEvent* aEvent);
+
+#endif /* __nsQtKeyUtils_h__ */
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsScreenManagerQt.cpp
@@ -0,0 +1,144 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Lars Knoll <knoll@kde.org>
+ *   Zack Rusin <zack@kde.org>
+ *   John C. Griggs <johng@corel.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsScreenManagerQt.h"
+#include "nsScreenQt.h"
+
+#include "qdesktopwidget.h"
+#include "qapplication.h"
+
+nsScreenManagerQt::nsScreenManagerQt()
+{
+    desktop = 0;
+}
+
+
+nsScreenManagerQt::~nsScreenManagerQt()
+{
+    // nothing to see here.
+}
+
+// addref, release, QI
+NS_IMPL_ISUPPORTS1(nsScreenManagerQt, nsIScreenManager)
+
+void nsScreenManagerQt::init()
+{
+    if (desktop)
+        return;
+
+    desktop = QApplication::desktop();
+    nScreens = desktop->numScreens();
+    screens = new nsCOMPtr<nsIScreen>[nScreens];
+
+    for (int i = 0; i < nScreens; ++i)
+        screens[i] = new nsScreenQt(i);
+}
+
+//
+// ScreenForRect
+//
+// Returns the screen that contains the rectangle. If the rect overlaps
+// multiple screens, it picks the screen with the greatest area of intersection.
+//
+// The coordinates are in pixels (not twips) and in screen coordinates.
+//
+NS_IMETHODIMP
+nsScreenManagerQt::ScreenForRect(PRInt32 inLeft, PRInt32 inTop,
+				 PRInt32 inWidth, PRInt32 inHeight,
+				 nsIScreen **outScreen)
+{
+    if (!desktop)
+        init();
+
+    QRect r(inLeft, inTop, inWidth, inHeight);
+    int best = 0;
+    int area = 0;
+    for (int i = 0; i < nScreens; ++i) {
+        const QRect& rect = desktop->screenGeometry(i);
+        QRect intersection = r&rect;
+        int a = intersection.width()*intersection.height();
+        if (a > area) {
+            best = i;
+            area = a;
+        }
+    }
+
+    NS_IF_ADDREF(*outScreen = screens[best]);
+    return NS_OK;
+}
+
+//
+// GetPrimaryScreen
+//
+// The screen with the menubar/taskbar. This shouldn't be needed very
+// often.
+//
+NS_IMETHODIMP
+nsScreenManagerQt::GetPrimaryScreen(nsIScreen **aPrimaryScreen)
+{
+    if (!desktop)
+        init();
+
+    NS_IF_ADDREF(*aPrimaryScreen = screens[0]);
+    return NS_OK;
+}
+
+//
+// GetNumberOfScreens
+//
+// Returns how many physical screens are available.
+//
+NS_IMETHODIMP
+nsScreenManagerQt::GetNumberOfScreens(PRUint32 *aNumberOfScreens)
+{
+    if (!desktop)
+        init();
+
+    *aNumberOfScreens = desktop->numScreens();
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScreenManagerQt :: ScreenForNativeWidget (void *aWidget, nsIScreen **outScreen)
+{
+    // I don't know how to go from GtkWindow to nsIScreen, especially
+    // given xinerama and stuff, so let's just do this
+    QRect rect = static_cast<QWidget*>(aWidget)->geometry();
+    return ScreenForRect(rect.x(), rect.y(), rect.width(), rect.height(), outScreen);
+}
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsScreenManagerQt.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Lars Knoll <knoll@kde.org>
+ *   Zack Rusin <zack@kde.org>
+ *   John C. Griggs <johng@corel.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsScreenManagerQt_h___
+#define nsScreenManagerQt_h___
+
+#include "nsIScreenManager.h"
+#include "nsIScreen.h"
+#include "nsCOMPtr.h"
+
+//------------------------------------------------------------------------
+class QDesktopWidget;
+
+class nsScreenManagerQt : public nsIScreenManager
+{
+public:
+  nsScreenManagerQt ( );
+  virtual ~nsScreenManagerQt();
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSISCREENMANAGER
+
+private:
+
+  void init ();
+
+  nsCOMPtr<nsIScreen> *screens;
+  QDesktopWidget *desktop;
+  int nScreens;
+};
+
+#endif  // nsScreenManagerQt_h___
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsScreenQt.cpp
@@ -0,0 +1,103 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Lars Knoll <knoll@kde.org>
+ *   Zack Rusin <zack@kde.org>
+ *   John C. Griggs <johng@corel.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsScreenQt.h"
+
+#include <qcolor.h>
+#include <qcolormap.h>
+#include <qrect.h>
+#include <qdesktopwidget.h>
+#include <qapplication.h>
+
+nsScreenQt::nsScreenQt(int aScreen)
+    : mScreen(aScreen)
+{
+    // nothing else to do. I guess we could cache a bunch of information
+    // here, but we want to ask the device at runtime in case anything
+    // has changed.
+}
+
+nsScreenQt::~nsScreenQt()
+{
+    // nothing to see here.
+}
+
+// addref, release, QI
+NS_IMPL_ISUPPORTS1(nsScreenQt, nsIScreen)
+
+NS_IMETHODIMP
+nsScreenQt::GetRect(PRInt32 *outLeft,PRInt32 *outTop,
+                    PRInt32 *outWidth,PRInt32 *outHeight)
+{
+    QRect r = QApplication::desktop()->screenGeometry(mScreen);
+    *outTop = r.x();
+    *outLeft = r.y();
+    *outWidth = r.width();
+    *outHeight = r.height();
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScreenQt::GetAvailRect(PRInt32 *outLeft,PRInt32 *outTop,
+                         PRInt32 *outWidth,PRInt32 *outHeight)
+{
+    QRect r = QApplication::desktop()->availableGeometry(mScreen);
+    *outTop = r.x();
+    *outLeft = r.y();
+    *outWidth = r.width();
+    *outHeight = r.height();
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScreenQt::GetPixelDepth(PRInt32 *aPixelDepth)
+{
+    // #############
+    *aPixelDepth = (PRInt32)QColormap::instance().depth();
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScreenQt::GetColorDepth(PRInt32 *aColorDepth)
+{
+    // ###############
+    return GetPixelDepth(aColorDepth);
+}
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsScreenQt.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Lars Knoll <knoll@kde.org>
+ *   Zack Rusin <zack@kde.org>
+ *   John C. Griggs <johng@corel.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsScreenQt_h___
+#define nsScreenQt_h___
+
+#include "nsIScreen.h"
+
+//------------------------------------------------------------------------
+
+class nsScreenQt : public nsIScreen
+{
+public:
+  nsScreenQt (int aScreen);
+  virtual ~nsScreenQt();
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSISCREEN
+
+private:
+  int mScreen;
+};
+
+#endif  // nsScreenQt_h___
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsSound.cpp
@@ -0,0 +1,405 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <string.h>
+
+#include "nscore.h"
+#include "plstr.h"
+#include "prlink.h"
+
+#include "nsSound.h"
+
+#include "nsIURL.h"
+#include "nsIFileURL.h"
+#include "nsNetUtil.h"
+#include "nsCOMPtr.h"
+#include "nsNativeCharsetUtils.h"
+#include "nsAutoPtr.h"
+
+#include <QApplication>
+#include <QSound>
+
+/* used with esd_open_sound */
+static int esdref = -1;
+static PRLibrary *elib = nsnull;
+
+// the following from esd.h
+
+#define ESD_BITS8  (0x0000)
+#define ESD_BITS16 (0x0001) 
+#define ESD_MONO (0x0010)
+#define ESD_STEREO (0x0020) 
+#define ESD_STREAM (0x0000)
+#define ESD_PLAY (0x1000)
+
+#define WAV_MIN_LENGTH 44
+
+typedef int (PR_CALLBACK *EsdOpenSoundType)(const char *host);
+typedef int (PR_CALLBACK *EsdCloseType)(int);
+
+/* used to play the sounds from the find symbol call */
+typedef int (PR_CALLBACK *EsdPlayStreamType)  (int, 
+                                               int, 
+                                               const char *, 
+                                               const char *);
+typedef int  (PR_CALLBACK *EsdAudioOpenType)  (void);
+typedef int  (PR_CALLBACK *EsdAudioWriteType) (const void *, int);
+typedef void (PR_CALLBACK *EsdAudioCloseType) (void);
+
+NS_IMPL_ISUPPORTS2(nsSound, nsISound, nsIStreamLoaderObserver)
+
+nsSound::nsSound()
+ : mInited( PR_FALSE )
+{
+}
+
+nsSound::~nsSound()
+{
+    /* see above comment */
+    if (esdref != -1) {
+        EsdCloseType EsdClose = (EsdCloseType) PR_FindFunctionSymbol(elib, "esd_close");
+        if (EsdClose)
+            (*EsdClose)(esdref);
+        esdref = -1;
+    }
+}
+
+
+/**
+* unload esd library
+*/
+void
+nsSound::Shutdown()
+{
+    if (elib) {
+        PR_UnloadLibrary(elib);
+        elib = nsnull;
+    }
+}
+
+NS_IMETHODIMP
+nsSound::Init()
+{
+    /* we don't need to do esd_open_sound if we are only going to play files
+       but we will if we want to do things like streams, etc
+    */
+    if (mInited) 
+        return NS_OK;
+    if (elib) 
+        return NS_OK;
+
+    EsdOpenSoundType EsdOpenSound;
+
+    elib = PR_LoadLibrary("libesd.so.0");
+    if (!elib) return NS_ERROR_FAILURE;
+
+    EsdOpenSound = (EsdOpenSoundType) PR_FindFunctionSymbol(elib, "esd_open_sound");
+
+    if (!EsdOpenSound)
+        return NS_ERROR_FAILURE;
+
+    esdref = (*EsdOpenSound)("localhost");
+
+    if (!esdref)
+        return NS_ERROR_FAILURE;
+
+    mInited = PR_TRUE;
+
+    return NS_OK;
+}
+
+NS_METHOD nsSound::Beep()
+{
+    QApplication::beep();
+    return NS_OK;
+}
+
+
+/**
+* This can't be implemented directly with QT.
+* (We can use QSound to play local files but that was not enough.
+* Also support of media formats is limited)
+*
+* Current implementation is copied from GTK side and implementation uses ESD interface.
+*
+* If we have Qtopia then we can drop ESD implementation and use Qtopia "Multimedia API"
+*/
+NS_IMETHODIMP nsSound::OnStreamComplete(nsIStreamLoader *aLoader,
+                                        nsISupports *context,
+                                        nsresult aStatus,
+                                        PRUint32 dataLen,
+                                        const PRUint8 *data)
+{
+
+#define GET_WORD(s, i) (s[i+1] << 8) | s[i]
+#define GET_DWORD(s, i) (s[i+3] << 24) | (s[i+2] << 16) | (s[i+1] << 8) | s[i]
+
+    // print a load error on bad status, and return
+    if (NS_FAILED(aStatus)) {
+#ifdef DEBUG
+        if (aLoader) {
+            nsCOMPtr<nsIRequest> request;
+            aLoader->GetRequest(getter_AddRefs(request));
+            if (request) {
+                nsCOMPtr<nsIURI> uri;
+                nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
+                if (channel) {
+                      channel->GetURI(getter_AddRefs(uri));
+                      if (uri) {
+                            nsCAutoString uriSpec;
+                            uri->GetSpec(uriSpec);
+                            printf("Failed to load %s\n", uriSpec.get());
+                      }
+                }
+            }
+        }
+#endif
+        return aStatus;
+    }
+
+    int fd, mask = 0;
+    PRUint32 samples_per_sec = 0, avg_bytes_per_sec = 0, chunk_len = 0;
+    PRUint16 format, channels = 1, bits_per_sample = 0;
+    const PRUint8 *audio = nsnull;
+    size_t audio_len = 0;
+
+    if (dataLen < 4) {
+        NS_WARNING("Sound stream too short to determine its type");
+        return NS_ERROR_FAILURE;
+    }
+
+    if (memcmp(data, "RIFF", 4)) {
+#ifdef DEBUG
+        printf("We only support WAV files currently.\n");
+#endif
+        return NS_ERROR_FAILURE;
+    }
+
+    if (dataLen <= WAV_MIN_LENGTH) {
+        NS_WARNING("WAV files should be longer than 44 bytes.");
+        return NS_ERROR_FAILURE;
+    }
+
+    PRUint32 i = 12;
+    while (i + 7 < dataLen) {
+        if (!memcmp(data + i, "fmt ", 4) && !chunk_len) {
+            i += 4;
+
+            /* length of the rest of this subblock (should be 16 for PCM data */
+            chunk_len = GET_DWORD(data, i);
+            i += 4;
+
+            if (chunk_len < 16 || i + chunk_len >= dataLen) {
+                NS_WARNING("Invalid WAV file: bad fmt chunk.");
+                return NS_ERROR_FAILURE;
+            }
+
+            format = GET_WORD(data, i);
+            i += 2;
+
+            channels = GET_WORD(data, i);
+            i += 2;
+
+            samples_per_sec = GET_DWORD(data, i);
+            i += 4;
+
+            avg_bytes_per_sec = GET_DWORD(data, i);
+            i += 4;
+
+            // block align
+            i += 2;
+
+            bits_per_sample = GET_WORD(data, i);
+            i += 2;
+
+            /* we don't support WAVs with odd compression codes */
+            if (chunk_len != 16)
+                NS_WARNING("Extra format bits found in WAV. Ignoring");
+
+            i += chunk_len - 16;
+        } else if (!memcmp(data + i, "data", 4)) {
+            i += 4;
+            if (!chunk_len) {
+                NS_WARNING("Invalid WAV file: no fmt chunk found");
+                return NS_ERROR_FAILURE;
+            }
+
+            audio_len = GET_DWORD(data, i);
+            i += 4;
+
+            /* try to play truncated WAVs */
+            if (i + audio_len > dataLen)
+                audio_len = dataLen - i;
+
+            audio = data + i;
+            break;
+        } else {
+            i += 4;
+            i += GET_DWORD(data, i);
+            i += 4;
+        }
+    }
+
+    if (!audio) {
+        NS_WARNING("Invalid WAV file: no data chunk found");
+        return NS_ERROR_FAILURE;
+    }
+
+    /* No audio data? well, at least the WAV was valid. */
+    if (!audio_len)
+        return NS_OK;
+
+#if 0
+    printf("f: %d | c: %d | sps: %li | abps: %li | ba: %d | bps: %d | rate: %li\n",
+         format, channels, samples_per_sec, avg_bytes_per_sec, block_align, bits_per_sample, rate);
+#endif
+
+    /* open up connection to esd */  
+    EsdPlayStreamType EsdPlayStream = 
+        (EsdPlayStreamType) PR_FindFunctionSymbol(elib, 
+                                                  "esd_play_stream");
+    if (!EsdPlayStream)
+        return NS_ERROR_FAILURE;
+
+    mask = ESD_PLAY | ESD_STREAM;
+
+    if (bits_per_sample == 8)
+        mask |= ESD_BITS8;
+    else 
+        mask |= ESD_BITS16;
+
+    if (channels == 1)
+        mask |= ESD_MONO;
+    else 
+        mask |= ESD_STEREO;
+
+    nsAutoArrayPtr<PRUint8> buf;
+
+    // ESD only handle little-endian data. 
+    // Swap the byte order if we're on a big-endian architecture.
+#ifdef IS_BIG_ENDIAN
+    if (bits_per_sample != 8) {
+        buf = new PRUint8[audio_len];
+        if (!buf)
+            return NS_ERROR_OUT_OF_MEMORY;
+        for (PRUint32 j = 0; j + 2 < audio_len; j += 2) {
+            buf[j]     = audio[j + 1];
+            buf[j + 1] = audio[j];
+        }
+
+    audio = buf;
+    }
+#endif
+
+    fd = (*EsdPlayStream)(mask, samples_per_sec, NULL, "mozillaSound"); 
+  
+    if (fd < 0) {
+      int *esd_audio_format = (int *) PR_FindSymbol(elib, "esd_audio_format");
+      int *esd_audio_rate = (int *) PR_FindSymbol(elib, "esd_audio_rate");
+      EsdAudioOpenType EsdAudioOpen = (EsdAudioOpenType) PR_FindFunctionSymbol(elib, "esd_audio_open");
+      EsdAudioWriteType EsdAudioWrite = (EsdAudioWriteType) PR_FindFunctionSymbol(elib, "esd_audio_write");
+      EsdAudioCloseType EsdAudioClose = (EsdAudioCloseType) PR_FindFunctionSymbol(elib, "esd_audio_close");
+
+      if (!esd_audio_format || !esd_audio_rate ||
+          !EsdAudioOpen || !EsdAudioWrite || !EsdAudioClose)
+          return NS_ERROR_FAILURE;
+
+      *esd_audio_format = mask;
+      *esd_audio_rate = samples_per_sec;
+      fd = (*EsdAudioOpen)();
+
+      if (fd < 0)
+        return NS_ERROR_FAILURE;
+
+      (*EsdAudioWrite)(audio, audio_len);
+      (*EsdAudioClose)();
+    } else {
+      while (audio_len > 0) {
+        size_t written = write(fd, audio, audio_len);
+        if (written <= 0)
+          break;
+        audio += written;
+        audio_len -= written;
+      }
+      close(fd);
+    }
+
+    return NS_OK;
+}
+
+NS_METHOD nsSound::Play(nsIURL *aURL)
+{
+    nsresult rv;
+
+    if (!mInited)
+        Init();
+
+    if (!elib) 
+        return NS_ERROR_FAILURE;
+
+    nsCOMPtr<nsIStreamLoader> loader;
+    rv = NS_NewStreamLoader(getter_AddRefs(loader), aURL, this);
+
+    return rv;
+}
+
+NS_IMETHODIMP nsSound::PlaySystemSound(const nsAString &aSoundAlias)
+{
+    if (aSoundAlias.EqualsLiteral("_moz_mailbeep")) {
+        return Beep();
+    }
+
+    nsresult rv;
+    nsCOMPtr <nsIURI> fileURI;
+
+    // create a nsILocalFile and then a nsIFileURL from that
+    nsCOMPtr <nsILocalFile> soundFile;
+    rv = NS_NewLocalFile(aSoundAlias, PR_TRUE, 
+                         getter_AddRefs(soundFile));
+    NS_ENSURE_SUCCESS(rv,rv);
+
+    rv = NS_NewFileURI(getter_AddRefs(fileURI), soundFile);
+    NS_ENSURE_SUCCESS(rv,rv);
+
+    nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(fileURI,&rv);
+    NS_ENSURE_SUCCESS(rv,rv);
+
+    rv = Play(fileURL);
+    return rv;
+
+}
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsSound.h
@@ -0,0 +1,63 @@
+/*
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __nsSound_h__
+#define __nsSound_h__
+
+#include "nsISound.h"
+#include "nsIStreamLoader.h"
+
+class nsSound : public nsISound,
+                public nsIStreamLoaderObserver
+{
+ public:
+
+  nsSound();
+  virtual ~nsSound();
+
+  static void Shutdown();
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSISOUND
+  NS_DECL_NSISTREAMLOADEROBSERVER
+
+private:
+  PRBool mInited;
+
+};
+
+#endif /* __nsSound_h__ */
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsToolkit.cpp
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Lars Knoll <knoll@kde.org>
+ *   Zack Rusin <zack@kde.org>
+ *   John C. Griggs <johng@corel.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nscore.h"  // needed for 'nsnull'
+#include "nsToolkit.h"
+#include "nsGUIEvent.h"
+#include "nsWidgetAtoms.h"
+//#include "plevent.h"
+
+// Static thread local storage index of the Toolkit
+// object associated with a given thread...
+static PRUintn gToolkitTLSIndex = 0;
+
+//-------------------------------------------------------------------------
+// constructor
+//-------------------------------------------------------------------------
+nsToolkit::nsToolkit()
+{
+}
+
+//-------------------------------------------------------------------------
+// destructor
+//-------------------------------------------------------------------------
+nsToolkit::~nsToolkit()
+{
+  // Remove the TLS reference to the toolkit...
+  PR_SetThreadPrivate(gToolkitTLSIndex, nsnull);
+}
+
+//-------------------------------------------------------------------------
+// nsISupports implementation macro
+//-------------------------------------------------------------------------
+NS_IMPL_ISUPPORTS1(nsToolkit, nsIToolkit)
+
+//-------------------------------------------------------------------------
+NS_IMETHODIMP nsToolkit::Init(PRThread *aThread)
+{
+  nsWidgetAtoms::RegisterAtoms();
+
+  return NS_OK;
+}
+
+//-------------------------------------------------------------------------
+// Return the nsIToolkit for the current thread.  If a toolkit does not
+// yet exist, then one will be created...
+//-------------------------------------------------------------------------
+NS_METHOD NS_GetCurrentToolkit(nsIToolkit* *aResult)
+{
+  nsIToolkit* toolkit = nsnull;
+  nsresult rv = NS_OK;
+  PRStatus status;
+
+  // Create the TLS index the first time through...
+  if (0 == gToolkitTLSIndex) {
+    status = PR_NewThreadPrivateIndex(&gToolkitTLSIndex, NULL);
+    if (PR_FAILURE == status) {
+      rv = NS_ERROR_FAILURE;
+    }
+  }
+  if (NS_SUCCEEDED(rv)) {
+    toolkit = (nsIToolkit*)PR_GetThreadPrivate(gToolkitTLSIndex);
+
+    // Create a new toolkit for this thread...
+    if (!toolkit) {
+      toolkit = new nsToolkit();
+
+      if (!toolkit) {
+        rv = NS_ERROR_OUT_OF_MEMORY;
+      }
+      else {
+        NS_ADDREF(toolkit);
+        toolkit->Init(PR_GetCurrentThread());
+
+        // The reference stored in the TLS is weak.  It is removed in the
+        // nsToolkit destructor...
+        PR_SetThreadPrivate(gToolkitTLSIndex, (void*)toolkit);
+       }
+    }
+    else {
+      NS_ADDREF(toolkit);
+    }
+    *aResult = toolkit;
+  }
+  return rv;
+}
+
+void nsToolkit::CreateSharedGC(void)
+{
+    if (mSharedGC)
+        return;
+
+    mSharedGC = new QPixmap();
+}
+
+Qt::HANDLE
+nsToolkit::GetSharedGC(void)
+{
+    // FIXME Not sure
+    return mSharedGC->handle();
+}
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsToolkit.h
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   John C. Griggs <johng@corel.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nsToolkit_h__      
+#define nsToolkit_h__
+
+#include "nsIToolkit.h"
+#include "nsString.h"
+#include <QPixmap>
+
+/**
+ * Wrapper around the thread running the message pump.
+ * The toolkit abstraction is necessary because the message pump must
+ * execute within the same thread that created the widget under Win32.
+ */ 
+class nsToolkit : public nsIToolkit
+{
+public:
+    nsToolkit();
+    virtual ~nsToolkit();
+
+    void          CreateSharedGC(void);
+    Qt::HANDLE    GetSharedGC(void);
+
+    /**
+     * Get/set our value of DESKTOP_STARTUP_ID. When non-empty, this is applied
+     * to the next toplevel window to be shown or focused (and then immediately
+     * cleared).
+     */ 
+    void SetDesktopStartupID(const nsACString& aID) { mDesktopStartupID = aID; }
+    void GetDesktopStartupID(nsACString* aID) { *aID = mDesktopStartupID; }
+
+    /**
+     * Get/set the timestamp value to be used, if non-zero, to focus the
+     * next top-level window to be shown or focused (upon which it is cleared).
+     */
+    void SetFocusTimestamp(PRUint32 aTimestamp) { mFocusTimestamp = aTimestamp; }
+    PRUint32 GetFocusTimestamp() { return mFocusTimestamp; }
+
+    NS_DECL_ISUPPORTS
+    NS_IMETHOD Init(PRThread *aThread);
+
+private:
+    nsCString      mDesktopStartupID;
+    PRUint32       mFocusTimestamp;
+    QPixmap        *mSharedGC;
+};
+
+#endif  // nsToolkit_h__
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsWidgetFactory.cpp
@@ -0,0 +1,193 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * John C. Griggs <johng@corel.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Zack Rusin <zack@kde.org>
+ *   Lars Knoll <knoll@kde.org>
+ *   John C. Griggs <johng@corel.com>
+ *   Dan Rosen <dr@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIGenericFactory.h"
+#include "nsIModule.h"
+
+#include "nsCOMPtr.h"
+#include "nsWidgetsCID.h"
+#include "nsAppShell.h"
+#include "nsWindow.h"
+#include "nsToolkit.h"
+#include "nsHTMLFormatConverter.h"
+#include "nsTransferable.h"
+#include "nsLookAndFeel.h"
+#include "nsAppShellSingleton.h"
+#include "nsScreenManagerQt.h"
+
+// #include "nsIComponentRegistrar.h"
+// #include "nsComponentManagerUtils.h"
+// #include "nsAutoPtr.h"
+// 
+
+
+#include "nsFilePicker.h"
+#include "nsClipboard.h"
+#include "nsClipboardHelper.h"
+#include "nsIdleServiceQt.h"
+#include "nsDragService.h"
+#include "nsSound.h"
+#include "nsBidiKeyboard.h"
+#include "nsNativeThemeQt.h"
+// #include "nsScrollbar.h"
+// 
+// #include "nsGUIEvent.h"
+// #include "nsQtEventDispatcher.h"
+// #include "nsIRenderingContext.h"
+// #include "nsIServiceManager.h"
+// #include "nsGfxCIID.h"
+// #include "nsIPrefBranch.h"
+// #include "nsIPrefService.h"
+// 
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsChildWindow)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsPopupWindow)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsToolkit)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsLookAndFeel)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerQt)
+
+/*
+static NS_DEFINE_CID(kNativeScrollCID, NS_NATIVESCROLLBAR_CID);
+*/
+
+
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboard)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsIdleServiceQt)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsNativeThemeQt)
+//NS_GENERIC_FACTORY_CONSTRUCTOR(nsNativeScrollbar)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePicker)
+
+
+static const nsModuleComponentInfo components[] =
+{
+    { "Qt nsWindow",
+      NS_WINDOW_CID,
+      "@mozilla.org/widgets/window/qt;1",
+      nsWindowConstructor },
+    { "Qt Child nsWindow",
+      NS_CHILD_CID,
+      "@mozilla.org/widgets/child_window/qt;1",
+      nsChildWindowConstructor },
+    { "Qt AppShell",
+      NS_APPSHELL_CID,
+      "@mozilla.org/widget/appshell/qt;1",
+      nsAppShellConstructor },
+    { "Qt Look And Feel",
+      NS_LOOKANDFEEL_CID,
+      "@mozilla.org/widget/lookandfeel/qt;1",
+      nsLookAndFeelConstructor },
+    { "Qt Popup nsWindow",
+      NS_POPUP_CID,
+      "@mozilla.org/widgets/popup_window/qt;1",
+      nsPopupWindowConstructor },
+    { "HTML Format Converter",
+      NS_HTMLFORMATCONVERTER_CID,
+      "@mozilla.org/widget/htmlformatconverter/qt;1",
+      nsHTMLFormatConverterConstructor },
+    { "Qt Toolkit",
+      NS_TOOLKIT_CID,
+      "@mozilla.org/widget/toolkit/qt;1",
+      nsToolkitConstructor },
+    { "Transferrable",
+      NS_TRANSFERABLE_CID,
+      "@mozilla.org/widget/transferable;1",
+      nsTransferableConstructor },
+    { "Qt Screen Manager",
+      NS_SCREENMANAGER_CID,
+      "@mozilla.org/gfx/screenmanager;1",
+      nsScreenManagerQtConstructor },
+    { "Qt Clipboard",
+      NS_CLIPBOARD_CID,
+      "@mozilla.org/widget/clipboard;1",
+      nsClipboardConstructor },
+    { "Clipboard Helper",
+      NS_CLIPBOARDHELPER_CID,
+      "@mozilla.org/widget/clipboardhelper;1",
+      nsClipboardHelperConstructor },
+    { "Qt Drag Service",
+      NS_DRAGSERVICE_CID,
+      "@mozilla.org/widget/dragservice;1",
+      nsDragServiceConstructor },
+    { "Qt Bidi Keyboard",
+      NS_BIDIKEYBOARD_CID,
+      "@mozilla.org/widget/bidikeyboard;1",
+      nsBidiKeyboardConstructor },
+#ifdef Q_WS_X11
+    { "Qt Idle Service",
+       NS_IDLE_SERVICE_CID,
+       "@mozilla.org/widget/idleservice;1",
+       nsIdleServiceQtConstructor },
+#endif
+    { "Qt Sound",
+      NS_SOUND_CID,
+      "@mozilla.org/sound;1",
+      nsSoundConstructor },
+    { "Native Theme Renderer",
+      NS_THEMERENDERER_CID,
+      "@mozilla.org/chrome/chrome-native-theme;1",
+      nsNativeThemeQtConstructor },
+    { "Qt File Picker",
+      NS_FILEPICKER_CID,
+      "@mozilla.org/filepicker;1",
+      nsFilePickerConstructor }
+
+};
+
+PR_STATIC_CALLBACK(void)
+nsWidgetQtModuleDtor(nsIModule *aSelf)
+{
+    nsSound::Shutdown();
+    nsAppShellShutdown(aSelf);
+}
+
+NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(nsWidgetQtModule,
+                                   components,
+                                   nsAppShellInit,
+                                   nsWidgetQtModuleDtor)
+
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsWindow.cpp
@@ -0,0 +1,2622 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Christopher Blizzard
+ * <blizzard@mozilla.org>.  Portions created by the Initial Developer
+ * are Copyright (C) 2001 the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Mats Palmgren <mats.palmgren@bredband.net>
+ *   Masayuki Nakano <masayuki@d-toybox.com>
+ *   Romashin Oleg <romaxa@gmail.com>
+ *   Vladimir Vukicevic <vladimir@pobox.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "prlink.h"
+
+#include <qevent.h> //XXX switch for forward-decl
+#include <QtGui>
+#include <qcursor.h>
+
+#include "nsWindow.h"
+#include "nsToolkit.h"
+#include "nsIDeviceContext.h"
+#include "nsIRenderingContext.h"
+#include "nsIRegion.h"
+#include "nsIRollupListener.h"
+#include "nsIMenuRollup.h"
+#include "nsIDOMNode.h"
+
+#include "nsWidgetsCID.h"
+#include "nsIDragService.h"
+
+#include "nsQtKeyUtils.h"
+
+#ifdef Q_WS_X11
+#include <X11/XF86keysym.h>
+#endif
+
+#include "nsWidgetAtoms.h"
+
+#ifdef MOZ_ENABLE_STARTUP_NOTIFICATION
+#define SN_API_NOT_YET_FROZEN
+#include <startup-notification-1.0/libsn/sn.h>
+#endif
+
+#include "nsIPrefService.h"
+#include "nsIPrefBranch.h"
+#include "nsIServiceManager.h"
+#include "nsIStringBundle.h"
+#include "nsGfxCIID.h"
+
+/* For SetIcon */
+#include "nsAppDirectoryServiceDefs.h"
+#include "nsXPIDLString.h"
+#include "nsIFile.h"
+#include "nsILocalFile.h"
+
+/* SetCursor(imgIContainer*) */
+#include "imgIContainer.h"
+#include "gfxIImageFrame.h"
+#include "nsGfxCIID.h"
+#include "nsIImage.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "nsAutoPtr.h"
+
+#include "gfxQtPlatform.h"
+#include "gfxXlibSurface.h"
+#include "gfxQPainterSurface.h"
+#include "gfxContext.h"
+#include "gfxImageSurface.h"
+
+#include <qapplication.h>
+#include <qdesktopwidget.h>
+#include <qwidget.h>
+#include <qcursor.h>
+#include <qobject.h>
+#include <execinfo.h>
+#include <stdlib.h>
+
+#ifdef Q_WS_X11
+#include "qx11info_x11.h"
+#endif
+
+#include <execinfo.h>
+
+#include "mozqwidget.h"
+
+/* For PrepareNativeWidget */
+static NS_DEFINE_IID(kDeviceContextCID, NS_DEVICE_CONTEXT_CID);
+
+// initialization static functions 
+static nsresult    initialize_prefs        (void);
+
+static NS_DEFINE_IID(kCDragServiceCID,  NS_DRAGSERVICE_CID);
+
+#define NS_WINDOW_TITLE_MAX_LENGTH 4095
+
+#define kWindowPositionSlop 20
+
+// QT
+static const int WHEEL_DELTA = 120;
+static PRBool gGlobalsInitialized = PR_FALSE;
+
+static nsCOMPtr<nsIRollupListener> gRollupListener;
+static nsWeakPtr                   gRollupWindow;
+static PRBool                      gConsumeRollupEvent;
+
+//static nsWindow * get_window_for_qt_widget(QWidget *widget);
+
+static PRBool     check_for_rollup(double aMouseX, double aMouseY,
+                                   PRBool aIsWheel);
+static PRBool
+is_mouse_in_window (QWidget* aWindow, double aMouseX, double aMouseY);
+
+static PRBool
+isContextMenuKeyEvent(const QKeyEvent *qe)
+{
+    PRUint32 kc = QtKeyCodeToDOMKeyCode(qe->key());
+    if (qe->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier))
+        return PR_FALSE;
+
+    PRBool isShift = qe->modifiers() & Qt::ShiftModifier;
+    return (kc == NS_VK_F10 && isShift) ||
+        (kc == NS_VK_CONTEXT_MENU && !isShift);
+}
+
+static void
+InitKeyEvent(nsKeyEvent &aEvent, QKeyEvent *aQEvent)
+{
+    aEvent.isShift   = aQEvent->modifiers() & Qt::ShiftModifier;
+    aEvent.isControl = aQEvent->modifiers() & Qt::ControlModifier;
+    aEvent.isAlt     = aQEvent->modifiers() & Qt::AltModifier;
+    aEvent.isMeta    = aQEvent->modifiers() & Qt::MetaModifier;
+    aEvent.time      = 0;
+
+    // The transformations above and in gdk for the keyval are not invertible
+    // so link to the GdkEvent (which will vanish soon after return from the
+    // event callback) to give plugins access to hardware_keycode and state.
+    // (An XEvent would be nice but the GdkEvent is good enough.)
+    aEvent.nativeMsg = (void *)aQEvent;
+}
+
+static void
+keyEventToContextMenuEvent(const nsKeyEvent* aKeyEvent,
+                           nsMouseEvent* aCMEvent)
+{
+    memcpy(aCMEvent, aKeyEvent, sizeof(nsInputEvent));
+//    aCMEvent->message = NS_CONTEXTMENU_KEY;
+    aCMEvent->isShift = aCMEvent->isControl = PR_FALSE;
+    aCMEvent->isControl = PR_FALSE;
+    aCMEvent->isAlt = aCMEvent->isMeta = PR_FALSE;
+    aCMEvent->isMeta = PR_FALSE;
+    aCMEvent->clickCount = 0;
+    aCMEvent->acceptActivation = PR_FALSE;
+}
+
+nsWindow::nsWindow()
+{
+    LOG(("%s [%p]\n", __PRETTY_FUNCTION__, (void *)this));
+    
+    mIsTopLevel       = PR_FALSE;
+    mIsDestroyed      = PR_FALSE;
+    mIsShown          = PR_FALSE;
+    mEnabled          = PR_TRUE;
+
+    mPreferredWidth   = 0;
+    mPreferredHeight  = 0;
+
+    mDrawingArea         = nsnull;
+    mIsVisible           = PR_FALSE;
+    mActivatePending     = PR_FALSE;
+    mWindowType          = eWindowType_child;
+    mSizeState           = nsSizeMode_Normal;
+    mPluginType          = PluginType_NONE;
+    mQCursor             = Qt::ArrowCursor;
+
+    if (!gGlobalsInitialized) {
+        gGlobalsInitialized = PR_TRUE;
+
+        // It's OK if either of these fail, but it may not be one day.
+        initialize_prefs();
+    }
+
+    memset(mKeyDownFlags, 0, sizeof(mKeyDownFlags));
+
+    mIsTransparent = PR_FALSE;
+
+    mCursor = eCursor_standard;
+}
+
+nsWindow::~nsWindow()
+{
+    LOG(("%s [%p]\n", __PRETTY_FUNCTION__, (void *)this));
+    
+    Destroy();
+}
+
+/* XXX - this gets called right after CreateQWidget, which also
+ * sets mDrawingArea.  We probably want to always pass a MozQWidget
+ * here; things won't really work at all with any generic widget.
+ */
+void
+nsWindow::Initialize(QWidget *widget)
+{
+    LOG(("%s [%p]\n", __PRETTY_FUNCTION__, (void *)this));
+
+    Q_ASSERT(widget);
+
+    mDrawingArea = widget;
+    mDrawingArea->setMouseTracking(PR_TRUE);
+    mDrawingArea->setFocusPolicy(Qt::WheelFocus);
+}
+
+/* static */ void
+nsWindow::ReleaseGlobals()
+{
+}
+
+NS_IMPL_ISUPPORTS_INHERITED1(nsWindow, nsBaseWidget, nsISupportsWeakReference)
+
+NS_IMETHODIMP
+nsWindow::Create(nsIWidget        *aParent,
+                 const nsRect     &aRect,
+                 EVENT_CALLBACK   aHandleEventFunction,
+                 nsIDeviceContext *aContext,
+                 nsIAppShell      *aAppShell,
+                 nsIToolkit       *aToolkit,
+                 nsWidgetInitData *aInitData)
+{
+    LOG(("%s [%p]\n", __PRETTY_FUNCTION__, (void *)this));
+
+    nsresult rv = NativeCreate(aParent, nsnull, aRect, aHandleEventFunction,
+                               aContext, aAppShell, aToolkit, aInitData);
+    return rv;
+}
+
+NS_IMETHODIMP
+nsWindow::Create(nsNativeWidget aParent,
+                 const nsRect     &aRect,
+                 EVENT_CALLBACK   aHandleEventFunction,
+                 nsIDeviceContext *aContext,
+                 nsIAppShell      *aAppShell,
+                 nsIToolkit       *aToolkit,
+                 nsWidgetInitData *aInitData)
+{
+    LOG(("%s [%p]\n", __PRETTY_FUNCTION__, (void *)this));
+
+    nsresult rv = NativeCreate(nsnull, aParent, aRect, aHandleEventFunction,
+                               aContext, aAppShell, aToolkit, aInitData);
+    return rv;
+}
+
+NS_IMETHODIMP
+nsWindow::Destroy(void)
+{
+    if (mIsDestroyed || !mDrawingArea)
+        return NS_OK;
+
+    LOG(("nsWindow::Destroy [%p]\n", (void *)this));
+    mIsDestroyed = PR_TRUE;
+
+    nsCOMPtr<nsIWidget> rollupWidget = do_QueryReferent(gRollupWindow);
+    if (static_cast<nsIWidget *>(this) == rollupWidget.get()) {
+        if (gRollupListener)
+            gRollupListener->Rollup(nsnull);
+        gRollupWindow = nsnull;
+        gRollupListener = nsnull;
+    }
+
+    Show(PR_FALSE);
+
+    // walk the list of children and call destroy on them.  Have to be
+    // careful, though -- calling destroy on a kid may actually remove
+    // it from our child list, losing its sibling links.
+    for (nsIWidget* kid = mFirstChild; kid; ) {
+        nsIWidget* next = kid->GetNextSibling();
+        kid->Destroy();
+        kid = next;
+    }
+
+    // Destroy thebes surface now. Badness can happen if we destroy
+    // the surface after its X Window.
+    mThebesSurface = nsnull;
+
+    if (mMozQWidget) {
+        mMozQWidget->dropReceiver();
+
+        // Call deleteLater instead of delete; Qt still needs the object
+        // to be valid even after sending it a Close event.  We could
+        // also set WA_DeleteOnClose, but this gives us more control.
+        mMozQWidget->deleteLater();
+    }
+
+    mDrawingArea = nsnull;
+
+    OnDestroy();
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::SetParent(nsIWidget *aNewParent)
+{
+    NS_ENSURE_ARG_POINTER(aNewParent);
+
+    QWidget* newParentWindow =
+        static_cast<QWidget*>(aNewParent->GetNativeData(NS_NATIVE_WINDOW));
+    NS_ASSERTION(newParentWindow, "Parent widget has a null native window handle");
+
+    if (mDrawingArea) {
+        qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
+        // moz_drawingarea_reparent(mDrawingArea, newParentWindow);
+    } else {
+        NS_NOTREACHED("nsWindow::SetParent - reparenting a non-child window");
+    }
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::SetModal(PRBool aModal)
+{
+    LOG(("nsWindow::SetModal [%p] %d, widget[%p]\n", (void *)this, aModal, mDrawingArea));
+
+    MozQWidget *mozWidget = static_cast<MozQWidget*>(mDrawingArea);
+    if (mozWidget)
+        mozWidget->setModal(aModal);
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::IsVisible(PRBool & aState)
+{
+    aState = mDrawingArea?mDrawingArea->isVisible():PR_FALSE;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::ConstrainPosition(PRBool aAllowSlop, PRInt32 *aX, PRInt32 *aY)
+{
+    if (mDrawingArea) {
+        PRInt32 screenWidth  = QApplication::desktop()->width();
+        PRInt32 screenHeight = QApplication::desktop()->height();
+        if (aAllowSlop) {
+            if (*aX < (kWindowPositionSlop - mBounds.width))
+                *aX = kWindowPositionSlop - mBounds.width;
+            if (*aX > (screenWidth - kWindowPositionSlop))
+                *aX = screenWidth - kWindowPositionSlop;
+            if (*aY < (kWindowPositionSlop - mBounds.height))
+                *aY = kWindowPositionSlop - mBounds.height;
+            if (*aY > (screenHeight - kWindowPositionSlop))
+                *aY = screenHeight - kWindowPositionSlop;
+        } else {
+            if (*aX < 0)
+                *aX = 0;
+            if (*aX > (screenWidth - mBounds.width))
+                *aX = screenWidth - mBounds.width;
+            if (*aY < 0)
+                *aY = 0;
+            if (*aY > (screenHeight - mBounds.height))
+                *aY = screenHeight - mBounds.height;
+        }
+    }
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::Move(PRInt32 aX, PRInt32 aY)
+{
+    LOG(("nsWindow::Move [%p] %d %d\n", (void *)this,
+         aX, aY));
+
+    // Since a popup window's x/y coordinates are in relation to to
+    // the parent, the parent might have moved so we always move a
+    // popup window.
+    //bool popup = mDrawingArea ? mDrawingArea->windowType() == Qt::Popup : false;
+    if (aX == mBounds.x && aY == mBounds.y &&
+        mWindowType != eWindowType_popup)
+        return NS_OK;
+
+    // XXX Should we do some AreBoundsSane check here?
+
+
+    if (!mDrawingArea)
+        return NS_OK;
+
+    QPoint pos(aX, aY);
+    if (mDrawingArea) {
+        if (mParent && mDrawingArea->windowType() == Qt::Popup) {
+            nsRect oldrect, newrect;
+            oldrect.x = aX;
+            oldrect.y = aY;
+
+            mParent->WidgetToScreen(oldrect, newrect);
+
+            pos = QPoint(newrect.x, newrect.y);
+#ifdef DEBUG_WIDGETS
+            qDebug("pos is [%d,%d]", pos.x(), pos.y());
+#endif
+        } else {
+            qDebug("Widget within another? (%p)", (void*)mDrawingArea);
+        }
+    }
+
+    mBounds.x = pos.x();
+    mBounds.y = pos.y();
+
+    mDrawingArea->move(pos);
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::PlaceBehind(nsTopLevelWidgetZPlacement  aPlacement,
+                      nsIWidget                  *aWidget,
+                      PRBool                      aActivate)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsWindow::SetZIndex(PRInt32 aZIndex)
+{
+    nsIWidget* oldPrev = GetPrevSibling();
+
+    nsBaseWidget::SetZIndex(aZIndex);
+
+    if (GetPrevSibling() == oldPrev) {
+        return NS_OK;
+    }
+
+    NS_ASSERTION(!mDrawingArea, "Expected Mozilla child widget");
+
+    // We skip the nsWindows that don't have mDrawingAreas.
+    // These are probably in the process of being destroyed.
+
+    if (!GetNextSibling()) {
+        // We're to be on top.
+        if (mDrawingArea) {
+            qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
+            // gdk_window_raise(mDrawingArea->clip_window);
+        }
+    } else {
+        // All the siblings before us need to be below our widget. 
+        for (nsWindow* w = this; w;
+             w = static_cast<nsWindow*>(w->GetPrevSibling())) {
+            if (w->mDrawingArea) {
+                qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
+                // gdk_window_lower(w->mDrawingArea->clip_window);
+            }
+        }
+    }
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::SetSizeMode(PRInt32 aMode)
+{
+    nsresult rv;
+
+    LOG(("nsWindow::SetSizeMode [%p] %d\n", (void *)this, aMode));
+
+    // Save the requested state.
+    rv = nsBaseWidget::SetSizeMode(aMode);
+
+    // return if there's no shell or our current state is the same as
+    // the mode we were just set to.
+    if (!mDrawingArea || mSizeState == mSizeMode) {
+        return rv;
+    }
+
+    switch (aMode) {
+    case nsSizeMode_Maximized:
+        mDrawingArea->showMaximized();
+        break;
+    case nsSizeMode_Minimized:
+        mDrawingArea->showMinimized();
+        break;
+    default:
+        // nsSizeMode_Normal, really.
+        mDrawingArea->showNormal ();
+        // KILLME
+        //if (mSizeState == nsSizeMode_Minimized)
+        //    gtk_window_deiconify(GTK_WINDOW(mDrawingArea));
+        //else if (mSizeState == nsSizeMode_Maximized)
+        //    gtk_window_unmaximize(GTK_WINDOW(mDrawingArea));
+        break;
+    }
+
+    mSizeState = mSizeMode;
+
+    return rv;
+}
+
+typedef void (* SetUserTimeFunc)(QWidget* aWindow, quint32 aTimestamp);
+
+// This will become obsolete when new GTK APIs are widely supported,
+// as described here: http://bugzilla.gnome.org/show_bug.cgi?id=347375
+/*
+static void
+SetUserTimeAndStartupIDForActivatedWindow(QWidget* aWindow)
+{
+    nsCOMPtr<nsIToolkit> toolkit;
+    NS_GetCurrentToolkit(getter_AddRefs(toolkit));
+    if (!toolkit)
+        return;
+
+    nsToolkit* QTToolkit = static_cast<nsToolkit*>
+                                          (static_cast<nsIToolkit*>(toolkit));
+    nsCAutoString desktopStartupID;
+    QTToolkit->GetDesktopStartupID(&desktopStartupID);
+    if (desktopStartupID.IsEmpty()) {
+        // We don't have the data we need. Fall back to an
+        // approximation ... using the timestamp of the remote command
+        // being received as a guess for the timestamp of the user event
+        // that triggered it.
+        PRUint32 timestamp = QTToolkit->GetFocusTimestamp();
+        if (timestamp) {
+            aWindow->focusWidget ();
+            // gdk_window_focus(aWindow->window, timestamp);
+            QTToolkit->SetFocusTimestamp(0);
+        }
+        return;
+    }
+
+    QTToolkit->SetDesktopStartupID(EmptyCString());
+}
+*/
+
+NS_IMETHODIMP
+nsWindow::SetFocus(PRBool aRaise)
+{
+    // Make sure that our owning widget has focus.  If it doesn't try to
+    // grab it.  Note that we don't set our focus flag in this case.
+
+    LOGFOCUS(("  SetFocus [%p]\n", (void *)this));
+
+    if (!mDrawingArea)
+        return NS_ERROR_FAILURE;
+
+    if (aRaise)
+        mDrawingArea->raise();
+    mDrawingArea->setFocus();
+
+    // If there is already a focused child window, dispatch a LOSTFOCUS
+    // event from that widget and unset its got focus flag.
+
+    LOGFOCUS(("  widget now has focus - dispatching events [%p]\n",
+              (void *)this));
+
+    DispatchGotFocusEvent();
+
+    LOGFOCUS(("  done dispatching events in SetFocus() [%p]\n",
+              (void *)this));
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::GetScreenBounds(nsRect &aRect)
+{
+    nsRect origin(0, 0, mBounds.width, mBounds.height);
+    WidgetToScreen(origin, aRect);
+    LOG(("GetScreenBounds %d %d | %d %d | %d %d\n",
+         aRect.x, aRect.y,
+         mBounds.width, mBounds.height,
+         aRect.width, aRect.height));
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::SetForegroundColor(const nscolor &aColor)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsWindow::SetBackgroundColor(const nscolor &aColor)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsWindow::SetCursor(nsCursor aCursor)
+{
+    mCursor = aCursor;
+    if (mMozQWidget)
+        mMozQWidget->SetCursor(mCursor);
+    return NS_OK;
+}
+
+/*
+static
+PRUint8* Data32BitTo1Bit(PRUint8* aImageData,
+                         PRUint32 aImageBytesPerRow,
+                         PRUint32 aWidth, PRUint32 aHeight)
+{
+  PRUint32 outBpr = (aWidth + 7) / 8;
+
+  PRUint8* outData = new PRUint8[outBpr * aHeight];
+  if (!outData)
+      return NULL;
+
+  PRUint8 *outRow = outData,
+          *imageRow = aImageData;
+
+  for (PRUint32 curRow = 0; curRow < aHeight; curRow++) {
+      PRUint8 *irow = imageRow;
+      PRUint8 *orow = outRow;
+      PRUint8 imagePixels = 0;
+      PRUint8 offset = 0;
+
+      for (PRUint32 curCol = 0; curCol < aWidth; curCol++) {
+          PRUint8 r = *imageRow++,
+                  g = *imageRow++,
+                  b = *imageRow++;
+                  imageRow++;
+
+          if ((r + b + g) < 3 * 128)
+              imagePixels |= (1 << offset);
+
+          if (offset == 7) {
+              *outRow++ = imagePixels;
+              offset = 0;
+              imagePixels = 0;
+          } else {
+              offset++;
+          }
+      }
+      if (offset != 0)
+          *outRow++ = imagePixels;
+
+      imageRow = irow + aImageBytesPerRow;
+      outRow = orow + outBpr;
+  }
+
+  return outData;
+}
+*/
+
+
+NS_IMETHODIMP
+nsWindow::SetCursor(imgIContainer* aCursor,
+                    PRUint32 aHotspotX, PRUint32 aHotspotY)
+{
+    nsresult rv = NS_ERROR_OUT_OF_MEMORY;
+    qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
+    return rv;
+}
+
+
+NS_IMETHODIMP
+nsWindow::Validate()
+{
+    // Get the update for this window and, well, just drop it on the
+    // floor.
+    if (!mDrawingArea)
+        return NS_OK;
+
+    qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::Invalidate(PRBool aIsSynchronous)
+{
+    LOGDRAW(("Invalidate (all) [%p]: \n", (void *)this));
+
+    if (!mDrawingArea)
+        return NS_OK;
+
+    if (aIsSynchronous && !mDrawingArea->paintingActive())
+        mDrawingArea->repaint();
+    else
+        mDrawingArea->update();
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::Invalidate(const nsRect &aRect,
+                     PRBool        aIsSynchronous)
+{
+    LOGDRAW(("Invalidate (rect) [%p,%p]: %d %d %d %d (sync: %d)\n", (void *)this,
+             (void*)mDrawingArea,aRect.x, aRect.y, aRect.width, aRect.height, aIsSynchronous));
+
+    if (!mDrawingArea)
+        return NS_OK;
+
+    if (aIsSynchronous)
+        mDrawingArea->repaint(aRect.x, aRect.y, aRect.width, aRect.height);
+    else {
+        mDrawingArea->update(aRect.x, aRect.y, aRect.width, aRect.height);
+    }
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::InvalidateRegion(const nsIRegion* aRegion,
+                           PRBool           aIsSynchronous)
+{
+
+    QRegion *region = nsnull;
+    aRegion->GetNativeRegion((void *&)region);
+
+    if (region && mDrawingArea) {
+        QRect rect = region->boundingRect();
+
+//        LOGDRAW(("Invalidate (region) [%p]: %d %d %d %d (sync: %d)\n",
+//                 (void *)this,
+//                 rect.x, rect.y, rect.width, rect.height, aIsSynchronous));
+
+        if (aIsSynchronous && !mDrawingArea->paintingActive())
+            mDrawingArea->repaint(*region);
+        else
+            mDrawingArea->update(*region);
+    }
+    else {
+        qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
+        LOGDRAW(("Invalidate (region) [%p] with empty region\n",
+                 (void *)this));
+    }
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::Update()
+{
+    if (!mDrawingArea)
+        return NS_OK;
+
+    // mDrawingArea->update(); // FIXME  This call cause update for whole window on each scroll event
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::SetColorMap(nsColorMap *aColorMap)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsWindow::Scroll(PRInt32  aDx,
+                 PRInt32  aDy,
+                 nsRect  *aClipRect)
+{
+    if (!mDrawingArea)
+        return NS_OK;
+
+    mDrawingArea->scroll(aDx, aDy);
+
+    // Update bounds on our child windows
+    for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
+        nsRect bounds;
+        kid->GetBounds(bounds);
+        bounds.x += aDx;
+        bounds.y += aDy;
+        static_cast<nsBaseWidget*>(kid)->SetBounds(bounds);
+    }
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::ScrollWidgets(PRInt32 aDx,
+                        PRInt32 aDy)
+{
+    if (!mDrawingArea)
+        return NS_OK;
+
+    mDrawingArea->scroll(aDx, aDy);
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::ScrollRect(nsRect  &aSrcRect,
+                     PRInt32  aDx,
+                     PRInt32  aDy)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+void*
+nsWindow::GetNativeData(PRUint32 aDataType)
+{
+    switch (aDataType) {
+    case NS_NATIVE_WINDOW:
+    case NS_NATIVE_WIDGET: {
+        if (!mDrawingArea)
+            return nsnull;
+
+        return mDrawingArea;
+        break;
+    }
+
+    case NS_NATIVE_PLUGIN_PORT:
+        return SetupPluginPort();
+        break;
+
+#ifdef Q_WS_X11
+    case NS_NATIVE_DISPLAY:
+        return mDrawingArea->x11Info().display();
+        break;
+#endif
+
+    case NS_NATIVE_GRAPHIC: {
+        NS_ASSERTION(nsnull != mToolkit, "NULL toolkit, unable to get a GC");
+        return (void *)static_cast<nsToolkit *>(mToolkit)->GetSharedGC();
+        break;
+    }
+
+    case NS_NATIVE_SHELLWIDGET:
+        return (void *) mDrawingArea;
+
+    default:
+        NS_WARNING("nsWindow::GetNativeData called with bad value");
+        return nsnull;
+    }
+}
+
+NS_IMETHODIMP
+nsWindow::SetBorderStyle(nsBorderStyle aBorderStyle)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsWindow::SetTitle(const nsAString& aTitle)
+{
+    if (mDrawingArea) {
+        QString qStr(QString::fromUtf16(aTitle.BeginReading(), aTitle.Length()));
+        mDrawingArea->setWindowTitle(qStr);
+    }
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::SetIcon(const nsAString& aIconSpec)
+{
+    if (!mDrawingArea)
+        return NS_OK;
+
+    nsCOMPtr<nsILocalFile> iconFile;
+    nsCAutoString path;
+    nsCStringArray iconList;
+
+    // Look for icons with the following suffixes appended to the base name.
+    // The last two entries (for the old XPM format) will be ignored unless
+    // no icons are found using the other suffixes. XPM icons are depricated.
+
+    const char extensions[6][7] = { ".png", "16.png", "32.png", "48.png",
+                                    ".xpm", "16.xpm" };
+
+    for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(extensions); i++) {
+        // Don't bother looking for XPM versions if we found a PNG.
+        if (i == NS_ARRAY_LENGTH(extensions) - 2 && iconList.Count())
+            break;
+
+        nsAutoString extension;
+        extension.AppendASCII(extensions[i]);
+
+        ResolveIconName(aIconSpec, extension, getter_AddRefs(iconFile));
+        if (iconFile) {
+            iconFile->GetNativePath(path);
+            iconList.AppendCString(path);
+        }
+    }
+
+    // leave the default icon intact if no matching icons were found
+    if (iconList.Count() == 0)
+        return NS_OK;
+
+    return SetWindowIconList(iconList);
+}
+
+NS_IMETHODIMP
+nsWindow::ShowMenuBar(PRBool aShow)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsWindow::WidgetToScreen(const nsRect& aOldRect, nsRect& aNewRect)
+{
+    NS_ENSURE_TRUE(mDrawingArea, NS_OK);
+
+    QPoint origin(aOldRect.x, aOldRect.y);
+    origin = mDrawingArea->mapToGlobal(origin);
+
+    aNewRect.x = origin.x();
+    aNewRect.y = origin.y();
+    aNewRect.width = aOldRect.width;
+    aNewRect.height = aOldRect.height;
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::ScreenToWidget(const nsRect& aOldRect, nsRect& aNewRect)
+{
+    NS_ENSURE_TRUE(mDrawingArea, NS_OK);
+
+    QPoint origin(aOldRect.x, aOldRect.y);
+    origin = mDrawingArea->mapFromGlobal(origin);
+
+    aNewRect.x = origin.x();
+    aNewRect.y = origin.y();
+    aNewRect.width = aOldRect.width;
+    aNewRect.height = aOldRect.height;
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::BeginResizingChildren(void)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsWindow::EndResizingChildren(void)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsWindow::EnableDragDrop(PRBool aEnable)
+{
+    mDrawingArea->setAcceptDrops(aEnable);
+    return NS_OK;
+}
+
+void
+nsWindow::ConvertToDeviceCoordinates(nscoord &aX,
+                                     nscoord &aY)
+{
+}
+
+NS_IMETHODIMP
+nsWindow::PreCreateWidget(nsWidgetInitData *aWidgetInitData)
+{
+    if (nsnull != aWidgetInitData) {
+        mWindowType = aWidgetInitData->mWindowType;
+        mBorderStyle = aWidgetInitData->mBorderStyle;
+        return NS_OK;
+    }
+    return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsWindow::CaptureMouse(PRBool aCapture)
+{
+    LOG(("CaptureMouse %p\n", (void *)this));
+
+    if (!mDrawingArea)
+        return NS_OK;
+
+    if (aCapture)
+        mDrawingArea->grabMouse();
+    else
+        mDrawingArea->releaseMouse();
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::CaptureRollupEvents(nsIRollupListener *aListener,
+                              PRBool             aDoCapture,
+                              PRBool             aConsumeRollupEvent)
+{
+    if (!mDrawingArea)
+        return NS_OK;
+
+    LOG(("CaptureRollupEvents %p\n", (void *)this));
+
+    if (aDoCapture) {
+        gConsumeRollupEvent = aConsumeRollupEvent;
+        gRollupListener = aListener;
+        gRollupWindow = do_GetWeakReference(static_cast<nsIWidget*>(this));
+    }
+    else {
+        gRollupListener = nsnull;
+        gRollupWindow = nsnull;
+    }
+
+    return NS_OK;
+}
+
+PRBool
+check_for_rollup(double aMouseX, double aMouseY,
+                 PRBool aIsWheel)
+{
+    PRBool retVal = PR_FALSE;
+    nsCOMPtr<nsIWidget> rollupWidget = do_QueryReferent(gRollupWindow);
+
+    if (rollupWidget && gRollupListener) {
+        QWidget *currentPopup =
+            (QWidget *)rollupWidget->GetNativeData(NS_NATIVE_WINDOW);
+
+        if (!is_mouse_in_window(currentPopup, aMouseX, aMouseY)) {
+            PRBool rollup = PR_TRUE;
+            if (aIsWheel) {
+                gRollupListener->ShouldRollupOnMouseWheelEvent(&rollup);
+                retVal = PR_TRUE;
+            }
+            // if we're dealing with menus, we probably have submenus and
+            // we don't want to rollup if the clickis in a parent menu of
+            // the current submenu
+            nsCOMPtr<nsIMenuRollup> menuRollup;
+            menuRollup = (do_QueryInterface(gRollupListener));
+            if (menuRollup) {
+                nsAutoTArray<nsIWidget*, 5> widgetChain;
+                menuRollup->GetSubmenuWidgetChain(&widgetChain);
+                for (PRUint32 i=0; i<widgetChain.Length(); ++i) {
+                    nsIWidget* widget =  widgetChain[i];
+                    QWidget* currWindow =
+                        (QWidget*) widget->GetNativeData(NS_NATIVE_WINDOW);
+                    if (is_mouse_in_window(currWindow, aMouseX, aMouseY)) {
+                       rollup = PR_FALSE;
+                       break;
+                    }
+                } // foreach parent menu widget
+            } // if rollup listener knows about menus
+
+            // if we've determined that we should still rollup, do it.
+            if (rollup) {
+                gRollupListener->Rollup(nsnull);
+                retVal = PR_TRUE;
+            }
+        }
+    } else {
+        gRollupWindow = nsnull;
+        gRollupListener = nsnull;
+    }
+
+    return retVal;
+}
+
+/* static */
+PRBool
+is_mouse_in_window (QWidget* aWindow, double aMouseX, double aMouseY)
+{
+    int x = 0;
+    int y = 0;
+    int w, h;
+
+    x = aWindow->pos().x();
+    y = aWindow->pos().y();
+    w = aWindow->size().width();
+    h = aWindow->size().height();
+
+    if (aMouseX > x && aMouseX < x + w &&
+        aMouseY > y && aMouseY < y + h)
+        return PR_TRUE;
+
+    return PR_FALSE;
+}
+
+NS_IMETHODIMP
+nsWindow::GetAttention(PRInt32 aCycleCount)
+{
+    LOG(("nsWindow::GetAttention [%p]\n", (void *)this));
+
+    SetUrgencyHint(mDrawingArea, PR_TRUE);
+
+    return NS_OK;
+}
+
+void
+nsWindow::LoseFocus(void)
+{
+    // make sure that we reset our key down counter so the next keypress
+    // for this widget will get the down event
+    memset(mKeyDownFlags, 0, sizeof(mKeyDownFlags));
+
+    // Dispatch a lostfocus event
+    DispatchLostFocusEvent();
+
+    LOGFOCUS(("  widget lost focus [%p]\n", (void *)this));
+}
+
+static int gDoubleBuffering = -1;
+
+nsEventStatus
+nsWindow::OnPaintEvent(QPaintEvent *aEvent)
+{
+    //fprintf (stderr, "===== Expose start\n");
+
+    if (mIsDestroyed) {
+        LOG(("Expose event on destroyed window [%p] window %p\n",
+             (void *)this, mDrawingArea));
+        return nsEventStatus_eIgnore;
+    }
+
+    if (!mDrawingArea)
+        return nsEventStatus_eIgnore;
+
+    static NS_DEFINE_CID(kRegionCID, NS_REGION_CID);
+
+    nsCOMPtr<nsIRegion> updateRegion = do_CreateInstance(kRegionCID);
+    if (!updateRegion)
+        return nsEventStatus_eIgnore;
+
+    updateRegion->Init();
+
+    QVector<QRect>  rects = aEvent->region().rects();
+
+    LOGDRAW(("[%p] sending expose event %p 0x%lx (rects follow):\n",
+             (void *)this, (void *)aEvent, 0));
+
+    for (int i = 0; i < rects.size(); ++i) {
+       QRect r = rects.at(i);
+       updateRegion->Union(r.x(), r.y(), r.width(), r.height());
+       LOGDRAW(("\t%d %d %d %d\n", r.x(), r.y(), r.width(), r.height()));
+    }
+
+    QPainter painter;
+
+    if (!painter.begin(mDrawingArea)) {
+        fprintf (stderr, "*********** Failed to begin painting!\n");
+        return nsEventStatus_eConsumeNoDefault;
+    }
+
+    nsRefPtr<gfxQPainterSurface> targetSurface = new gfxQPainterSurface(&painter);
+    nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface);
+
+    nsCOMPtr<nsIRenderingContext> rc;
+    GetDeviceContext()->CreateRenderingContextInstance(*getter_AddRefs(rc));
+    if (NS_UNLIKELY(!rc))
+        return nsEventStatus_eIgnore;
+
+    rc->Init(GetDeviceContext(), ctx);
+
+    nsIntRect boundsRect;
+
+    updateRegion->GetBoundingBox(&boundsRect.x, &boundsRect.y,
+                                 &boundsRect.width, &boundsRect.height);
+
+    nsPaintEvent event(PR_TRUE, NS_PAINT, this);
+    QRect r = aEvent->rect();
+    if (!r.isValid())
+        r = mDrawingArea->rect();
+    nsRect rect(r.x(), r.y(), r.width(), r.height());
+    event.refPoint.x = aEvent->rect().x();
+    event.refPoint.y = aEvent->rect().y();
+    event.rect = &rect; // was null FIXME
+    event.region = updateRegion;
+    event.renderingContext = rc;
+
+    nsEventStatus status = DispatchEvent(&event);
+    //nsEventStatus status = nsEventStatus_eConsumeNoDefault;
+
+    // DispatchEvent can Destroy us (bug 378273), avoid doing any paint
+    // operations below if that happened - it will lead to XError and exit().
+    if (NS_UNLIKELY(mIsDestroyed))
+        return status;
+
+    if (status == nsEventStatus_eIgnore)
+        return status;
+
+    LOGDRAW(("[%p] draw done\n", this));
+
+    ctx = nsnull;
+    targetSurface = nsnull;
+
+    //fprintf (stderr, "===== Expose end\n");
+
+    // check the return value!
+    return status;
+}
+
+nsEventStatus
+nsWindow::OnMoveEvent(QMoveEvent *aEvent)
+{
+    LOG(("configure event [%p] %d %d\n", (void *)this,
+        aEvent->pos().x(),  aEvent->pos().y()));
+
+    // can we shortcut?
+    if (!mDrawingArea)
+        return nsEventStatus_eIgnore;
+
+    if ((mBounds.x == aEvent->pos().x() &&
+         mBounds.y == aEvent->pos().y()))
+    {
+        return nsEventStatus_eIgnore;
+    }
+
+    // Toplevel windows need to have their bounds set so that we can
+    // keep track of our location.  It's not often that the x,y is set
+    // by the layout engine.  Width and height are set elsewhere.
+    QPoint pos = aEvent->pos();
+    if (mIsTopLevel) {
+        // Need to translate this into the right coordinates
+        nsRect oldrect, newrect;
+        WidgetToScreen(oldrect, newrect);
+        mBounds.x = newrect.x;
+        mBounds.y = newrect.y;
+    }
+
+    nsGUIEvent event(PR_TRUE, NS_MOVE, this);
+
+    event.refPoint.x = pos.x();
+    event.refPoint.y = pos.y();
+
+    // XXX mozilla will invalidate the entire window after this move
+    // complete.  wtf?
+    return DispatchEvent(&event);
+}
+
+nsEventStatus
+nsWindow::OnResizeEvent(QResizeEvent *e)
+{
+    nsRect rect;
+
+    // Generate XPFE resize event
+    GetBounds(rect);
+
+    rect.width = e->size().width();
+    rect.height = e->size().height();
+
+    LOG(("size_allocate [%p] %d %d\n",
+         (void *)this, rect.width, rect.height));
+
+    mBounds.width = rect.width;
+    mBounds.height = rect.height;
+
+#ifdef DEBUG_WIDGETS
+    qDebug("resizeEvent: mDrawingArea=%p, aWidth=%d, aHeight=%d, aX = %d, aY = %d", (void*)mDrawingArea,
+           rect.width, rect.height, rect.x, rect.y);
+#endif
+
+    if (mDrawingArea)
+        mDrawingArea->resize(rect.width, rect.height);
+
+    nsEventStatus status;
+    DispatchResizeEvent(rect, status);
+    return status;
+}
+
+nsEventStatus
+nsWindow::OnCloseEvent(QCloseEvent *aEvent)
+{
+    nsGUIEvent event(PR_TRUE, NS_XUL_CLOSE, this);
+
+    event.refPoint.x = 0;
+    event.refPoint.y = 0;
+
+    return DispatchEvent(&event);
+}
+
+nsEventStatus
+nsWindow::OnEnterNotifyEvent(QEvent *aEvent)
+{
+    nsMouseEvent event(PR_TRUE, NS_MOUSE_ENTER, this, nsMouseEvent::eReal);
+
+    QPoint pt = QCursor::pos();
+
+    event.refPoint.x = nscoord(pt.x());
+    event.refPoint.y = nscoord(pt.y());
+
+    LOG(("OnEnterNotify: %p\n", (void *)this));
+
+    return DispatchEvent(&event);
+}
+
+nsEventStatus
+nsWindow::OnLeaveNotifyEvent(QEvent *aEvent)
+{
+    nsMouseEvent event(PR_TRUE, NS_MOUSE_EXIT, this, nsMouseEvent::eReal);
+
+    QPoint pt = QCursor::pos();
+
+    event.refPoint.x = nscoord(pt.x());
+    event.refPoint.y = nscoord(pt.y());
+
+    LOG(("OnLeaveNotify: %p\n", (void *)this));
+
+    return DispatchEvent(&event);
+}
+
+nsEventStatus
+nsWindow::OnMotionNotifyEvent(QMouseEvent *aEvent)
+{
+    // when we receive this, it must be that the gtk dragging is over,
+    // it is dropped either in or out of mozilla, clear the flag
+    //mDrawingArea->setCursor(mQCursor);
+
+    nsMouseEvent event(PR_TRUE, NS_MOUSE_MOVE, this, nsMouseEvent::eReal);
+
+
+    event.refPoint.x = nscoord(aEvent->x());
+    event.refPoint.y = nscoord(aEvent->y());
+
+    event.isShift         = aEvent->modifiers() & Qt::ShiftModifier;
+    event.isControl       = aEvent->modifiers() & Qt::ControlModifier;
+    event.isAlt           = aEvent->modifiers() & Qt::AltModifier;
+    event.isMeta          = aEvent->modifiers() & Qt::MetaModifier;
+    event.clickCount      = 0;
+
+    nsEventStatus status = DispatchEvent(&event);
+
+    //fprintf (stderr, "[%p] %p MotionNotify -> %d\n", this, mDrawingArea, status);
+
+    return status;
+}
+
+void
+nsWindow::InitButtonEvent(nsMouseEvent &event,
+                          QMouseEvent *aEvent, int aClickCount)
+{
+    event.refPoint.x = nscoord(aEvent->x());
+    event.refPoint.y = nscoord(aEvent->y());
+
+    event.isShift         = aEvent->modifiers() & Qt::ShiftModifier;
+    event.isControl       = aEvent->modifiers() & Qt::ControlModifier;
+    event.isAlt           = aEvent->modifiers() & Qt::AltModifier;
+    event.isMeta          = aEvent->modifiers() & Qt::MetaModifier;
+    event.clickCount      = aClickCount;
+}
+
+nsEventStatus
+nsWindow::OnButtonPressEvent(QMouseEvent *aEvent)
+{
+    PRBool rolledUp = check_for_rollup(aEvent->globalX(),
+                                       aEvent->globalY(), PR_FALSE);
+    if (gConsumeRollupEvent && rolledUp)
+        return nsEventStatus_eIgnore;
+
+    PRUint16      domButton;
+    switch (aEvent->button()) {
+    case Qt::MidButton:
+        domButton = nsMouseEvent::eMiddleButton;
+        break;
+    case Qt::RightButton:
+        domButton = nsMouseEvent::eRightButton;
+        break;
+    default:
+        domButton = nsMouseEvent::eLeftButton;
+        break;
+    }
+
+    nsMouseEvent event(PR_TRUE, NS_MOUSE_BUTTON_DOWN, this, nsMouseEvent::eReal);
+    event.button = domButton;
+    InitButtonEvent(event, aEvent, 1);
+
+    LOG(("%s [%p] button: %d\n", __PRETTY_FUNCTION__, (void*)this, domButton));
+
+    nsEventStatus status = DispatchEvent(&event);
+
+    // right menu click on linux should also pop up a context menu
+    if (domButton == nsMouseEvent::eRightButton &&
+        NS_LIKELY(!mIsDestroyed)) {
+        nsMouseEvent contextMenuEvent(PR_TRUE, NS_CONTEXTMENU, this,
+                                      nsMouseEvent::eReal);
+        InitButtonEvent(contextMenuEvent, aEvent, 1);
+        DispatchEvent(&contextMenuEvent, status);
+    }
+
+    //fprintf (stderr, "[%p] %p ButtonPress -> %d\n", this, mDrawingArea, status);
+
+    return status;
+}
+
+nsEventStatus
+nsWindow::OnButtonReleaseEvent(QMouseEvent *aEvent)
+{
+    PRUint16 domButton;
+//    mLastButtonReleaseTime = aEvent->time;
+
+    switch (aEvent->button()) {
+    case Qt::MidButton:
+        domButton = nsMouseEvent::eMiddleButton;
+        break;
+    case Qt::RightButton:
+        domButton = nsMouseEvent::eRightButton;
+        break;
+    default:
+        domButton = nsMouseEvent::eLeftButton;
+        break;
+    }
+
+    LOG(("%s [%p] button: %d\n", __PRETTY_FUNCTION__, (void*)this, domButton));
+
+    nsMouseEvent event(PR_TRUE, NS_MOUSE_BUTTON_UP, this, nsMouseEvent::eReal);
+    event.button = domButton;
+    InitButtonEvent(event, aEvent, 1);
+
+    nsEventStatus status = DispatchEvent(&event);
+
+    //fprintf (stderr, "[%p] %p ButtonRelease -> %d\n", this, mDrawingArea, status);
+
+    return status;
+}
+
+nsEventStatus
+nsWindow::mouseDoubleClickEvent(QMouseEvent *e)
+{
+    PRUint32      eventType;
+
+    switch (e->button()) {
+    case Qt::MidButton:
+        eventType = nsMouseEvent::eMiddleButton;
+        break;
+    case Qt::RightButton:
+        eventType = nsMouseEvent::eRightButton;
+        break;
+    default:
+        eventType = nsMouseEvent::eLeftButton;
+        break;
+    }
+
+    nsMouseEvent event(PR_TRUE, NS_MOUSE_DOUBLECLICK, this, nsMouseEvent::eReal);
+    event.button = eventType;
+
+    InitButtonEvent(event, e, 2);
+    //pressed
+    return DispatchEvent(&event);
+}
+
+nsEventStatus
+nsWindow::OnFocusInEvent(QFocusEvent *aEvent)
+{
+    LOGFOCUS(("OnFocusInEvent [%p]\n", (void *)this));
+    // Return if someone has blocked events for this widget.  This will
+    // happen if someone has called gtk_widget_grab_focus() from
+    // nsWindow::SetFocus() and will prevent recursion.
+
+    if (!mDrawingArea)
+        return nsEventStatus_eIgnore;
+
+    // Unset the urgency hint, if possible
+//    SetUrgencyHint(top_window, PR_FALSE);
+
+    // dispatch a got focus event
+    DispatchGotFocusEvent();
+
+    // send the activate event if it wasn't already sent via any
+    // SetFocus() calls that were the result of the GOTFOCUS event
+    // above.
+    DispatchActivateEvent();
+
+    LOGFOCUS(("Events sent from focus in event [%p]\n", (void *)this));
+    return nsEventStatus_eIgnore;
+}
+
+nsEventStatus
+nsWindow::OnFocusOutEvent(QFocusEvent *aEvent)
+{
+    LOGFOCUS(("OnFocusOutEvent [%p]\n", (void *)this));
+
+    DispatchLostFocusEvent();
+    if (mDrawingArea)
+        DispatchDeactivateEvent();
+
+    LOGFOCUS(("Done with container focus out [%p]\n", (void *)this));
+    return nsEventStatus_eIgnore;
+}
+
+inline PRBool
+is_latin_shortcut_key(quint32 aKeyval)
+{
+    return ((Qt::Key_0 <= aKeyval && aKeyval <= Qt::Key_9) ||
+            (Qt::Key_A <= aKeyval && aKeyval <= Qt::Key_Z));
+}
+
+PRBool
+nsWindow::DispatchCommandEvent(nsIAtom* aCommand)
+{
+    nsCommandEvent event(PR_TRUE, nsWidgetAtoms::onAppCommand, aCommand, this);
+
+    DispatchEvent(&event);
+
+    return TRUE;
+}
+
+nsEventStatus
+nsWindow::OnKeyPressEvent(QKeyEvent *aEvent)
+{
+    LOGFOCUS(("OnKeyPressEvent [%p]\n", (void *)this));
+
+    PRBool setNoDefault = PR_FALSE;
+
+    // before we dispatch a key, check if it's the context menu key.
+    // If so, send a context menu key event instead.
+    if (isContextMenuKeyEvent(aEvent)) {
+        nsMouseEvent contextMenuEvent(PR_TRUE, NS_CONTEXTMENU, this,
+                                      nsMouseEvent::eReal,
+                                      nsMouseEvent::eContextMenuKey);
+        //keyEventToContextMenuEvent(&event, &contextMenuEvent);
+        return DispatchEvent(&contextMenuEvent);
+    }
+
+    PRUint32 domCharCode = 0;
+    PRUint32 domKeyCode = QtKeyCodeToDOMKeyCode(aEvent->key());
+
+    if (aEvent->text().length() && aEvent->text()[0].isPrint())
+        domCharCode = (PRInt32) aEvent->text()[0].unicode();
+
+    // If the key isn't autorepeat, we need to send the initial down event
+    if (!aEvent->isAutoRepeat() && !IsKeyDown(domKeyCode)) {
+        // send the key down event
+
+        SetKeyDownFlag(domKeyCode);
+
+        nsKeyEvent downEvent(PR_TRUE, NS_KEY_DOWN, this);
+        InitKeyEvent(downEvent, aEvent);
+
+        downEvent.charCode = domCharCode;
+        downEvent.keyCode = domCharCode ? 0 : domKeyCode;
+
+        nsEventStatus status = DispatchEvent(&downEvent);
+
+        // If prevent default on keydown, do same for keypress
+        if (status == nsEventStatus_eConsumeNoDefault)
+            setNoDefault = PR_TRUE;
+    }
+
+    nsKeyEvent event(PR_TRUE, NS_KEY_PRESS, this);
+    InitKeyEvent(event, aEvent);
+
+    event.charCode = domCharCode;
+    event.keyCode = domCharCode ? 0 : domKeyCode;
+
+    if (setNoDefault)
+        event.flags |= NS_EVENT_FLAG_NO_DEFAULT;
+
+    // send the key press event
+    return DispatchEvent(&event);
+}
+
+nsEventStatus
+nsWindow::OnKeyReleaseEvent(QKeyEvent *aEvent)
+{
+    LOGFOCUS(("OnKeyReleaseEvent [%p]\n", (void *)this));
+
+    if (isContextMenuKeyEvent(aEvent)) {
+        // er, what do we do here? DoDefault or NoDefault?
+        return nsEventStatus_eConsumeDoDefault;
+    }
+
+    PRUint32 domCharCode = 0;
+    PRUint32 domKeyCode = QtKeyCodeToDOMKeyCode(aEvent->key());
+
+    if (aEvent->text().length() && aEvent->text()[0].isPrint())
+        domCharCode = (PRInt32) aEvent->text()[0].unicode();
+
+    // send the key event as a key up event
+    nsKeyEvent event(PR_TRUE, NS_KEY_UP, this);
+    InitKeyEvent(event, aEvent);
+
+    event.charCode = domCharCode;
+    event.keyCode = domCharCode ? 0 : domKeyCode;
+
+    // unset the key down flag
+    ClearKeyDownFlag(event.keyCode);
+
+    return DispatchEvent(&event);
+}
+
+nsEventStatus
+nsWindow::OnScrollEvent(QWheelEvent *aEvent)
+{
+    // check to see if we should rollup
+    nsMouseScrollEvent event(PR_TRUE, NS_MOUSE_SCROLL, this);
+
+    switch (aEvent->orientation()) {
+    case Qt::Vertical:
+        event.scrollFlags = nsMouseScrollEvent::kIsVertical;
+        break;
+    case Qt::Horizontal:
+        event.scrollFlags = nsMouseScrollEvent::kIsHorizontal;
+        break;
+    default:
+        Q_ASSERT(0);
+        break;
+    }
+
+    // negative values for aEvent->delta indicate downward scrolling;
+    // this is opposite Gecko usage.
+
+    event.delta = (int)(aEvent->delta() / WHEEL_DELTA) * -3;
+
+    event.refPoint.x = nscoord(aEvent->x());
+    event.refPoint.y = nscoord(aEvent->y());
+
+    event.isShift         = aEvent->modifiers() & Qt::ShiftModifier;
+    event.isControl       = aEvent->modifiers() & Qt::ControlModifier;
+    event.isAlt           = aEvent->modifiers() & Qt::AltModifier;
+    event.isMeta          = aEvent->modifiers() & Qt::MetaModifier;
+    event.time            = 0;
+
+    return DispatchEvent(&event);
+}
+
+
+nsEventStatus
+nsWindow::showEvent(QShowEvent *)
+{
+    LOG(("%s [%p]\n", __PRETTY_FUNCTION__,(void *)this));
+    // qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
+/*
+    QRect r = mDrawingArea->rect();
+    nsRect rect(r.x(), r.y(), r.width(), r.height());
+
+    nsCOMPtr<nsIRenderingContext> rc = getter_AddRefs(GetRenderingContext());
+       // Generate XPFE paint event
+    nsPaintEvent event(PR_TRUE, NS_PAINT, this);
+    event.refPoint.x = 0;
+    event.refPoint.y = 0;
+    event.rect = &rect;
+    // XXX fix this!
+    event.region = nsnull;
+    // XXX fix this!
+    event.renderingContext = rc;
+
+    return DispatchEvent(&event);
+*/
+    mIsVisible = PR_TRUE;
+    return nsEventStatus_eConsumeDoDefault;
+}
+
+nsEventStatus
+nsWindow::hideEvent(QHideEvent *)
+{
+    LOG(("%s [%p]\n", __PRETTY_FUNCTION__,(void *)this));
+    mIsVisible = PR_FALSE;
+    return nsEventStatus_eConsumeDoDefault;
+}
+
+nsEventStatus
+nsWindow::OnWindowStateEvent(QEvent *aEvent)
+{
+    qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
+    nsSizeModeEvent event(PR_TRUE, NS_SIZEMODE, this);
+    return DispatchEvent(&event);
+}
+
+void
+nsWindow::ThemeChanged()
+{
+    nsGUIEvent event(PR_TRUE, NS_THEMECHANGED, this);
+
+    DispatchEvent(&event);
+
+    if (!mDrawingArea || NS_UNLIKELY(mIsDestroyed))
+        return;
+    qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
+    return;
+}
+
+nsEventStatus
+nsWindow::OnDragMotionEvent(QDragMoveEvent *e)
+{
+    LOG(("nsWindow::OnDragMotionSignal\n"));
+
+    nsMouseEvent event(PR_TRUE, NS_DRAGDROP_OVER, 0,
+                       nsMouseEvent::eReal);
+    return nsEventStatus_eIgnore;
+}
+
+nsEventStatus
+nsWindow::OnDragLeaveEvent(QDragLeaveEvent *e)
+{
+    // XXX Do we want to pass this on only if the event's subwindow is null?
+    LOG(("nsWindow::OnDragLeaveSignal(%p)\n", this));
+    nsMouseEvent event(PR_TRUE, NS_DRAGDROP_EXIT, this, nsMouseEvent::eReal);
+
+    return DispatchEvent(&event);
+}
+
+nsEventStatus
+nsWindow::OnDragDropEvent(QDropEvent *aDropEvent)
+{
+    if (aDropEvent->proposedAction() == Qt::CopyAction)
+    {
+        printf("text version of the data: %s\n", aDropEvent->mimeData()->text().toAscii().data());
+        aDropEvent->acceptProposedAction();
+    }
+
+    LOG(("nsWindow::OnDragDropSignal\n"));
+    nsMouseEvent event(PR_TRUE, NS_DRAGDROP_OVER, 0,
+                       nsMouseEvent::eReal);
+    return nsEventStatus_eIgnore;
+}
+
+nsEventStatus
+nsWindow::OnDragEnter(QDragEnterEvent *aDragEvent)
+{
+#if 0
+    // TODO: Remove debugging prints
+    QStringList strings = aDragEvent->mimeData()->formats();
+    for (int i=0; i<strings.size(); ++i)
+    {
+        printf("%i: %s\n", i, strings.at(i).toLocal8Bit().constData());
+    }
+#endif
+
+    // Is it some format we think we can support?
+    if ( aDragEvent->mimeData()->hasFormat(kURLMime)
+      || aDragEvent->mimeData()->hasFormat(kURLDataMime)
+      || aDragEvent->mimeData()->hasFormat(kURLDescriptionMime)
+      || aDragEvent->mimeData()->hasFormat(kHTMLMime)
+      || aDragEvent->mimeData()->hasFormat(kUnicodeMime)
+      || aDragEvent->mimeData()->hasFormat(kTextMime)
+       )
+    {
+        aDragEvent->acceptProposedAction();
+    }
+
+    // XXX Do we want to pass this on only if the event's subwindow is null?
+
+    LOG(("nsWindow::OnDragEnter(%p)\n", this));
+
+    nsMouseEvent event(PR_TRUE, NS_DRAGDROP_ENTER, this, nsMouseEvent::eReal);
+    return DispatchEvent(&event);
+}
+
+static void
+GetBrandName(nsXPIDLString& brandName)
+{
+    nsCOMPtr<nsIStringBundleService> bundleService = 
+        do_GetService(NS_STRINGBUNDLE_CONTRACTID);
+
+    nsCOMPtr<nsIStringBundle> bundle;
+    if (bundleService)
+        bundleService->CreateBundle(
+            "chrome://branding/locale/brand.properties",
+            getter_AddRefs(bundle));
+
+    if (bundle)
+        bundle->GetStringFromName(
+            NS_LITERAL_STRING("brandShortName").get(),
+            getter_Copies(brandName));
+
+    if (brandName.IsEmpty())
+        brandName.Assign(NS_LITERAL_STRING("Mozilla"));
+}
+
+
+nsresult
+nsWindow::NativeCreate(nsIWidget        *aParent,
+                       nsNativeWidget    aNativeParent,
+                       const nsRect     &aRect,
+                       EVENT_CALLBACK    aHandleEventFunction,
+                       nsIDeviceContext *aContext,
+                       nsIAppShell      *aAppShell,
+                       nsIToolkit       *aToolkit,
+                       nsWidgetInitData *aInitData)
+{
+    // only set the base parent if we're going to be a dialog or a
+    // toplevel
+    nsIWidget *baseParent = aInitData &&
+        (aInitData->mWindowType == eWindowType_dialog ||
+         aInitData->mWindowType == eWindowType_toplevel ||
+         aInitData->mWindowType == eWindowType_invisible) ?
+        nsnull : aParent;
+
+    // initialize all the common bits of this class
+    BaseCreate(baseParent, aRect, aHandleEventFunction, aContext,
+               aAppShell, aToolkit, aInitData);
+
+    // and do our common creation
+    mParent = aParent;
+
+    // save our bounds
+    mBounds = aRect;
+
+    // figure out our parent window
+    QWidget      *parent = nsnull;
+    if (aParent != nsnull)
+        parent = (QWidget*)aParent->GetNativeData(NS_NATIVE_WIDGET);
+    else
+        parent = (QWidget*)aNativeParent;
+
+    // ok, create our windows
+    mDrawingArea = createQWidget(parent, aInitData);
+
+    Initialize(mDrawingArea);
+
+    LOG(("Create: nsWindow [%p] [%p]\n", (void *)this, (void *)mDrawingArea));
+
+    // resize so that everything is set to the right dimensions
+    Resize(mBounds.x, mBounds.y, mBounds.width, mBounds.height, PR_FALSE);
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::SetWindowClass(const nsAString &xulWinType)
+{
+  if (!mDrawingArea)
+    return NS_ERROR_FAILURE;
+
+  nsXPIDLString brandName;
+  GetBrandName(brandName);
+
+#ifdef Q_WS_X11
+  XClassHint *class_hint = XAllocClassHint();
+  if (!class_hint)
+    return NS_ERROR_OUT_OF_MEMORY;
+  const char *role = NULL;
+  class_hint->res_name = ToNewCString(xulWinType);
+  if (!class_hint->res_name) {
+    XFree(class_hint);
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+  class_hint->res_class = ToNewCString(brandName);
+  if (!class_hint->res_class) {
+    nsMemory::Free(class_hint->res_name);
+    XFree(class_hint);
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  // Parse res_name into a name and role. Characters other than
+  // [A-Za-z0-9_-] are converted to '_'. Anything after the first
+  // colon is assigned to role; if there's no colon, assign the
+  // whole thing to both role and res_name.
+  for (char *c = class_hint->res_name; *c; c++) {
+    if (':' == *c) {
+      *c = 0;
+      role = c + 1;
+    }
+    else if (!isascii(*c) || (!isalnum(*c) && ('_' != *c) && ('-' != *c)))
+      *c = '_';
+  }
+  class_hint->res_name[0] = toupper(class_hint->res_name[0]);
+  if (!role) role = class_hint->res_name;
+
+  // gdk_window_set_role(GTK_WIDGET(mDrawingArea)->window, role);
+  qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
+  // Can't use gtk_window_set_wmclass() for this; it prints
+  // a warning & refuses to make the change.
+  XSetClassHint(mDrawingArea->x11Info().display(),
+                mDrawingArea->handle(),
+                class_hint);
+  nsMemory::Free(class_hint->res_class);
+  nsMemory::Free(class_hint->res_name);
+  XFree(class_hint);
+#endif
+
+  return NS_OK;
+}
+
+void
+nsWindow::NativeResize(PRInt32 aWidth, PRInt32 aHeight, PRBool  aRepaint)
+{
+    LOG(("nsWindow::NativeResize [%p] %d %d\n", (void *)this,
+         aWidth, aHeight));
+
+    mDrawingArea->resize( aWidth, aHeight);
+
+    if (aRepaint)
+        mDrawingArea->update();
+}
+
+void
+nsWindow::NativeResize(PRInt32 aX, PRInt32 aY,
+                       PRInt32 aWidth, PRInt32 aHeight,
+                       PRBool  aRepaint)
+{
+    LOG(("nsWindow::NativeResize [%p] %d %d %d %d\n", (void *)this,
+         aX, aY, aWidth, aHeight));
+
+    QPoint pos(aX, aY);
+    if (mDrawingArea)
+    {
+        if (mParent && mDrawingArea->windowType() == Qt::Popup) {
+            nsRect oldrect, newrect;
+            oldrect.x = aX;
+            oldrect.y = aY;
+
+            mParent->WidgetToScreen(oldrect, newrect);
+
+            pos = QPoint(newrect.x, newrect.y);
+#ifdef DEBUG_WIDGETS
+            qDebug("pos is [%d,%d]", pos.x(), pos.y());
+#endif
+        } else {
+#ifdef DEBUG_WIDGETS
+            qDebug("Widget with original position? (%p)", mDrawingArea);
+#endif
+        }
+    }
+
+    mDrawingArea->setGeometry(pos.x(), pos.y(), aWidth, aHeight);
+
+    if (aRepaint)
+        mDrawingArea->update();
+}
+
+NS_IMETHODIMP
+nsWindow::SetHasTransparentBackground(PRBool aTransparent)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsWindow::GetHasTransparentBackground(PRBool& aTransparent)
+{
+    aTransparent = mIsTransparent;
+    return NS_OK;
+}
+
+void
+nsWindow::GetToplevelWidget(QWidget **aWidget)
+{
+    *aWidget = nsnull;
+
+    if (mDrawingArea) {
+        *aWidget = mDrawingArea;
+        return;
+    }
+}
+
+void
+nsWindow::SetUrgencyHint(QWidget *top_window, PRBool state)
+{
+    if (!top_window)
+        return;
+    qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
+/*
+    // Try to get a pointer to gdk_window_set_urgency_hint
+    PRLibrary* lib;
+    _gdk_window_set_urgency_hint_fn _gdk_window_set_urgency_hint = nsnull;
+    _gdk_window_set_urgency_hint = (_gdk_window_set_urgency_hint_fn)
+           PR_FindFunctionSymbolAndLibrary("gdk_window_set_urgency_hint", &lib);
+
+    if (_gdk_window_set_urgency_hint) {
+        _gdk_window_set_urgency_hint(top_window->window, state);
+        PR_UnloadLibrary(lib);
+    }
+    else if (state) {
+        gdk_window_show_unraised(top_window->window);
+    }
+*/
+}
+
+void *
+nsWindow::SetupPluginPort(void)
+{
+    if (!mDrawingArea)
+        return nsnull;
+
+    qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
+
+/*
+    // we have to flush the X queue here so that any plugins that
+    // might be running on separate X connections will be able to use
+    // this window in case it was just created
+    XWindowAttributes xattrs;
+    XGetWindowAttributes(Qt::Key_DISPLAY (),
+                         Qt::Key_WINDOW_XWINDOW(mDrawingArea->inner_window),
+                         &xattrs);
+    XSelectInput (Qt::Key_DISPLAY (),
+                  Qt::Key_WINDOW_XWINDOW(mDrawingArea->inner_window),
+                  xattrs.your_event_mask |
+                  SubstructureNotifyMask);
+
+    gdk_window_add_filter(mDrawingArea->inner_window,
+                          plugin_window_filter_func,
+                          this);
+
+    XSync(Qt::Key_DISPLAY(), False);
+
+    return (void *)Qt::Key_WINDOW_XWINDOW(mDrawingArea->inner_window);
+*/
+    return nsnull;
+}
+
+nsresult
+nsWindow::SetWindowIconList(const nsCStringArray &aIconList)
+{
+    qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
+    return NS_OK;
+}
+
+void
+nsWindow::SetDefaultIcon(void)
+{
+    SetIcon(NS_LITERAL_STRING("default"));
+}
+
+void
+nsWindow::SetPluginType(PluginType aPluginType)
+{
+    mPluginType = aPluginType;
+}
+
+void
+nsWindow::SetNonXEmbedPluginFocus()
+{
+    qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
+}
+
+void
+nsWindow::LoseNonXEmbedPluginFocus()
+{
+    qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
+    LOGFOCUS(("nsWindow::LoseNonXEmbedPluginFocus\n"));
+    LOGFOCUS(("nsWindow::LoseNonXEmbedPluginFocus end\n"));
+}
+
+
+qint32
+nsWindow::ConvertBorderStyles(nsBorderStyle aStyle)
+{
+    qint32 w = 0;
+
+    if (aStyle == eBorderStyle_default)
+        return -1;
+
+    qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
+/*
+    if (aStyle & eBorderStyle_all)
+        w |= Qt::Key_DECOR_ALL;
+    if (aStyle & eBorderStyle_border)
+        w |= Qt::Key_DECOR_BORDER;
+    if (aStyle & eBorderStyle_resizeh)
+        w |= Qt::Key_DECOR_RESIZEH;
+    if (aStyle & eBorderStyle_title)
+        w |= Qt::Key_DECOR_TITLE;
+    if (aStyle & eBorderStyle_menu)
+        w |= Qt::Key_DECOR_MENU;
+    if (aStyle & eBorderStyle_minimize)
+        w |= Qt::Key_DECOR_MINIMIZE;
+    if (aStyle & eBorderStyle_maximize)
+        w |= Qt::Key_DECOR_MAXIMIZE;
+    if (aStyle & eBorderStyle_close) {
+#ifdef DEBUG
+        printf("we don't handle eBorderStyle_close yet... please fix me\n");
+#endif
+    }
+*/
+    return w;
+}
+
+NS_IMETHODIMP
+nsWindow::MakeFullScreen(PRBool aFullScreen)
+{
+/*
+#if GTK_CHECK_VERSION(2,2,0)
+    if (aFullScreen)
+        gdk_window_fullscreen (mDrawingArea->window);
+    else
+        gdk_window_unfullscreen (mDrawingArea->window);
+    return NS_OK;
+#else
+*/
+    return nsBaseWidget::MakeFullScreen(aFullScreen);
+//#endif
+}
+
+NS_IMETHODIMP
+nsWindow::HideWindowChrome(PRBool aShouldHide)
+{
+    if (!mDrawingArea) {
+        // Pass the request to the toplevel window
+        QWidget *topWidget = nsnull;
+        GetToplevelWidget(&topWidget);
+//        return topWindow->HideWindowChrome(aShouldHide);
+        return NS_ERROR_FAILURE;
+    }
+
+    // Sawfish, metacity, and presumably other window managers get
+    // confused if we change the window decorations while the window
+    // is visible.
+    PRBool wasVisible = PR_FALSE;
+    if (mDrawingArea->isVisible()) {
+        mDrawingArea->hide();
+        wasVisible = PR_TRUE;
+    }
+
+    qint32 wmd;
+    if (aShouldHide)
+        wmd = 0;
+    else
+        wmd = ConvertBorderStyles(mBorderStyle);
+
+//    gdk_window_set_decorations(mDrawingArea->window, (GdkWMDecoration) wmd);
+
+    if (wasVisible) {
+        mDrawingArea->show();
+    }
+
+    // For some window managers, adding or removing window decorations
+    // requires unmapping and remapping our toplevel window.  Go ahead
+    // and flush the queue here so that we don't end up with a BadWindow
+    // error later when this happens (when the persistence timer fires
+    // and GetWindowPos is called)
+#ifdef Q_WS_X11
+    XSync(mDrawingArea->x11Info().display(), False);
+#endif
+
+    return NS_OK;
+}
+
+/* static */
+/*
+nsWindow *
+get_window_for_qt_widget(QWidget *widget)
+{
+    MozQWidget *mozWidget = static_cast<MozQWidget*>(widget);
+    return mozWidget->getReceiver();
+}
+*/
+
+//////////////////////////////////////////////////////////////////////
+// These are all of our drag and drop operations
+
+void
+nsWindow::InitDragEvent(nsMouseEvent &aEvent)
+{
+    // set the keyboard modifiers
+/*
+    qint32 x, y;
+
+    GdkModifierType state = (GdkModifierType)0;
+    gdk_window_get_pointer(NULL, &x, &y, &state);
+    aEvent.isShift = (state & Qt::Key_SHIFT_MASK) ? PR_TRUE : PR_FALSE;
+    aEvent.isControl = (state & Qt::Key_CONTROL_MASK) ? PR_TRUE : PR_FALSE;
+    aEvent.isAlt = (state & Qt::Key_MOD1_MASK) ? PR_TRUE : PR_FALSE;
+    aEvent.isMeta = PR_FALSE; // GTK+ doesn't support the meta key
+*/
+}
+
+// This will update the drag action based on the information in the
+// drag context.  Gtk gets this from a combination of the key settings
+// and what the source is offering.
+
+/* static */
+nsresult
+initialize_prefs(void)
+{
+    // check to see if we should set our raise pref
+    nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
+    if (!prefs)
+        return NS_OK;
+
+    PRBool val = PR_TRUE;
+    nsresult rv;
+    rv = prefs->GetBoolPref("mozilla.widget.raise-on-setfocus", &val);
+
+    return NS_OK;
+}
+
+inline PRBool
+is_context_menu_key(const nsKeyEvent& aKeyEvent)
+{
+    return ((aKeyEvent.keyCode == NS_VK_F10 && aKeyEvent.isShift &&
+             !aKeyEvent.isControl && !aKeyEvent.isMeta && !aKeyEvent.isAlt) ||
+            (aKeyEvent.keyCode == NS_VK_CONTEXT_MENU && !aKeyEvent.isShift &&
+             !aKeyEvent.isControl && !aKeyEvent.isMeta && !aKeyEvent.isAlt));
+}
+
+void
+key_event_to_context_menu_event(nsMouseEvent &aEvent,
+                                QKeyEvent *aGdkEvent)
+{
+    aEvent.refPoint = nsPoint(0, 0);
+    aEvent.isShift = PR_FALSE;
+    aEvent.isControl = PR_FALSE;
+    aEvent.isAlt = PR_FALSE;
+    aEvent.isMeta = PR_FALSE;
+    aEvent.time = 0;
+    aEvent.clickCount = 1;
+}
+
+/*
+static PRBool
+gdk_keyboard_get_modmap_masks(Display*  aDisplay,
+                              PRUint32* aCapsLockMask,
+                              PRUint32* aNumLockMask,
+                              PRUint32* aScrollLockMask)
+{
+    *aCapsLockMask = 0;
+    *aNumLockMask = 0;
+    *aScrollLockMask = 0;
+
+    int min_keycode = 0;
+    int max_keycode = 0;
+    XDisplayKeycodes(aDisplay, &min_keycode, &max_keycode);
+
+    int keysyms_per_keycode = 0;
+    KeySym* xkeymap = XGetKeyboardMapping(aDisplay, min_keycode,
+                                          max_keycode - min_keycode + 1,
+                                          &keysyms_per_keycode);
+    if (!xkeymap) {
+        return PR_FALSE;
+    }
+
+    XModifierKeymap* xmodmap = XGetModifierMapping(aDisplay);
+    if (!xmodmap) {
+        XFree(xkeymap);
+        return PR_FALSE;
+    }
+
+//      The modifiermap member of the XModifierKeymap structure contains 8 sets
+//      of max_keypermod KeyCodes, one for each modifier in the order Shift,
+//      Lock, Control, Mod1, Mod2, Mod3, Mod4, and Mod5.
+//      Only nonzero KeyCodes have meaning in each set, and zero KeyCodes are ignored.
+    const unsigned int map_size = 8 * xmodmap->max_keypermod;
+    for (unsigned int i = 0; i < map_size; i++) {
+        KeyCode keycode = xmodmap->modifiermap[i];
+        if (!keycode || keycode < min_keycode || keycode > max_keycode)
+            continue;
+
+        const KeySym* syms = xkeymap + (keycode - min_keycode) * keysyms_per_keycode;
+        const unsigned int mask = 1 << (i / xmodmap->max_keypermod);
+        for (int j = 0; j < keysyms_per_keycode; j++) {
+            switch (syms[j]) {
+                case Qt::Key_CapsLock:   *aCapsLockMask |= mask;   break;
+                case Qt::Key_NumLock:    *aNumLockMask |= mask;    break;
+                case Qt::Key_ScrollLock: *aScrollLockMask |= mask; break;
+            }
+        }
+    }
+
+    XFreeModifiermap(xmodmap);
+    XFree(xkeymap);
+    return PR_TRUE;
+}
+*/
+
+// nsChildWindow class
+
+nsChildWindow::nsChildWindow()
+{
+}
+
+nsChildWindow::~nsChildWindow()
+{
+}
+
+nsPopupWindow::nsPopupWindow()
+{
+    qDebug("===================== popup!");
+}
+
+nsPopupWindow::~nsPopupWindow()
+{
+}
+
+QWidget*
+nsWindow::createQWidget(QWidget *parent, nsWidgetInitData *aInitData)
+{
+    Qt::WFlags flags = Qt::Widget;
+    const char *windowName = NULL;
+
+    if (gDoubleBuffering == -1) {
+        if (getenv("MOZ_NO_DOUBLEBUFFER"))
+            gDoubleBuffering = 0;
+        else
+            gDoubleBuffering = 1;
+    }
+
+#ifdef DEBUG_WIDGETS
+    qDebug("NEW WIDGET\n\tparent is %p (%s)", (void*)parent,
+           parent ? qPrintable(parent->objectName()) : "null");
+#endif
+    // ok, create our windows
+    switch (mWindowType) {
+    case eWindowType_dialog:
+        flags |= Qt::Dialog;
+        windowName = "topLevelDialog";
+        break;
+    case eWindowType_popup:
+        flags |= Qt::ToolTip;
+        windowName = "topLevelPopup";
+        break;
+    case eWindowType_toplevel:
+        flags |= Qt::Window;
+        windowName = "topLevelWindow";
+        break;
+    case eWindowType_invisible:
+        flags |= Qt::Window;
+        windowName = "topLevelInvisible";
+        break;
+    case eWindowType_child:
+    default: // plugin, java, sheet
+        windowName = "paintArea";
+        break;
+    }
+
+    mMozQWidget = new MozQWidget(this, parent, windowName, flags);
+    mDrawingArea = mMozQWidget;
+ 
+    if (mWindowType == eWindowType_popup) {
+        mMozQWidget->setFocusPolicy(Qt::WheelFocus);
+ 
+        // XXX is this needed for Qt?
+        // gdk does not automatically set the cursor for "temporary"
+        // windows, which are what gtk uses for popups.
+        SetCursor(eCursor_standard);
+    } else if (mIsTopLevel) {
+        SetDefaultIcon();
+    }
+ 
+    mMozQWidget->setAttribute(Qt::WA_StaticContents);
+    mMozQWidget->setAttribute(Qt::WA_OpaquePaintEvent); // Transparent Widget Background
+    mMozQWidget->setAttribute(Qt::WA_NoSystemBackground);
+  
+    if (!gDoubleBuffering)
+        mMozQWidget->setAttribute(Qt::WA_PaintOnScreen);
+
+    return mDrawingArea;
+}
+
+// return the gfxASurface for rendering to this widget
+gfxASurface*
+nsWindow::GetThebesSurface()
+{
+    /* This is really a dummy surface; this is only used when doing reflow, because
+     * we need a RenderingContext to measure text against.
+     */
+    if (!mThebesSurface)
+        mThebesSurface = new gfxQPainterSurface(gfxIntSize(5,5), gfxASurface::CONTENT_COLOR);
+
+    return mThebesSurface;
+}
+
+NS_IMETHODIMP
+nsWindow::BeginResizeDrag(nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical)
+{
+    NS_ENSURE_ARG_POINTER(aEvent);
+
+
+    if (aEvent->eventStructType != NS_MOUSE_EVENT) {
+      // you can only begin a resize drag with a mouse event
+      return NS_ERROR_INVALID_ARG;
+    }
+
+    nsMouseEvent* mouse_event = static_cast<nsMouseEvent*>(aEvent);
+
+    if (mouse_event->button != nsMouseEvent::eLeftButton) {
+      // you can only begin a resize drag with the left mouse button
+      return NS_ERROR_INVALID_ARG;
+    }
+
+    qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
+
+    return NS_OK;
+}
+
+nsEventStatus
+nsWindow::contextMenuEvent(QContextMenuEvent *)
+{
+    //qDebug("context menu");
+    return nsEventStatus_eIgnore;
+}
+
+nsEventStatus
+nsWindow::imStartEvent(QEvent *)
+{
+    qWarning("XXX imStartEvent");
+    return nsEventStatus_eIgnore;
+}
+
+nsEventStatus
+nsWindow::imComposeEvent(QEvent *)
+{
+    qWarning("XXX imComposeEvent");
+    return nsEventStatus_eIgnore;
+}
+
+nsEventStatus
+nsWindow::imEndEvent(QEvent * )
+{
+    qWarning("XXX imComposeEvent");
+    return nsEventStatus_eIgnore;
+}
+
+nsIWidget *
+nsWindow::GetParent(void)
+{
+    return mParent;
+}
+
+void
+nsWindow::DispatchGotFocusEvent(void)
+{
+    nsGUIEvent event(PR_TRUE, NS_GOTFOCUS, this);
+    nsEventStatus status;
+    DispatchEvent(&event, status);
+}
+
+void
+nsWindow::DispatchLostFocusEvent(void)
+{
+    nsGUIEvent event(PR_TRUE, NS_LOSTFOCUS, this);
+    nsEventStatus status;
+    DispatchEvent(&event, status);
+}
+
+void
+nsWindow::DispatchActivateEvent(void)
+{
+    nsGUIEvent event(PR_TRUE, NS_ACTIVATE, this);
+    nsEventStatus status;
+    DispatchEvent(&event, status);
+}
+
+void
+nsWindow::DispatchDeactivateEvent(void)
+{
+    nsGUIEvent event(PR_TRUE, NS_DEACTIVATE, this);
+    nsEventStatus status;
+    DispatchEvent(&event, status);
+}
+
+void
+nsWindow::DispatchResizeEvent(nsRect &aRect, nsEventStatus &aStatus)
+{
+    nsSizeEvent event(PR_TRUE, NS_SIZE, this);
+
+    event.windowSize = &aRect;
+    event.refPoint.x = aRect.x;
+    event.refPoint.y = aRect.y;
+    event.mWinWidth = aRect.width;
+    event.mWinHeight = aRect.height;
+
+    nsEventStatus status;
+    DispatchEvent(&event, status); 
+}
+
+NS_IMETHODIMP
+nsWindow::DispatchEvent(nsGUIEvent *aEvent,
+                              nsEventStatus &aStatus)
+{
+#ifdef DEBUG
+    debug_DumpEvent(stdout, aEvent->widget, aEvent,
+                    nsCAutoString("something"), 0);
+#endif
+
+    aStatus = nsEventStatus_eIgnore;
+
+    // send it to the standard callback
+    if (mEventCallback)
+        aStatus = (* mEventCallback)(aEvent);
+
+    // dispatch to event listener if event was not consumed
+    if ((aStatus != nsEventStatus_eIgnore) && mEventListener)
+        aStatus = mEventListener->ProcessEvent(*aEvent);
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::Show(PRBool aState)
+{
+    LOG(("nsWindow::Show [%p] state %d\n", (void *)this, aState));
+
+    mIsShown = aState;
+
+    if (!mDrawingArea)
+        return NS_OK;
+
+    mDrawingArea->setVisible(aState);
+    if (mWindowType == eWindowType_popup && aState)
+        Resize(mBounds.x, mBounds.y, mBounds.width, mBounds.height, PR_FALSE);
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
+{
+    mBounds.width = aWidth;
+    mBounds.height = aHeight;
+
+    if (!mDrawingArea)
+        return NS_OK;
+
+    mDrawingArea->resize(aWidth, aHeight);
+
+    if (aRepaint)
+        mDrawingArea->update();
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight,
+                 PRBool aRepaint)
+{
+    mBounds.x = aX;
+    mBounds.y = aY;
+    mBounds.width = aWidth;
+    mBounds.height = aHeight;
+
+    mPlaced = PR_TRUE;
+
+    if (!mDrawingArea)
+        return NS_OK;
+
+    QPoint pos(aX, aY);
+
+    // XXXvlad what?
+#if 0
+    if (mParent && mDrawingArea->windowType() == Qt::Popup) {
+        nsRect oldrect, newrect;
+        oldrect.x = aX;
+        oldrect.y = aY;
+
+        mParent->WidgetToScreen(oldrect, newrect);
+
+        pos = QPoint(newrect.x, newrect.y);
+#ifdef DEBUG_WIDGETS
+        qDebug("pos is [%d,%d]", pos.x(), pos.y());
+#endif
+    } else {
+#ifdef DEBUG_WIDGETS
+        qDebug("Widget with original position? (%p)", mDrawingArea);
+#endif
+    }
+#endif
+
+    mDrawingArea->setGeometry(pos.x(), pos.y(), aWidth, aHeight);
+
+    if (aRepaint)
+        mDrawingArea->update();
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::GetPreferredSize(PRInt32 &aWidth,
+                                 PRInt32 &aHeight)
+{
+    aWidth  = mPreferredWidth;
+    aHeight = mPreferredHeight;
+    return (mPreferredWidth != 0 && mPreferredHeight != 0) ? 
+        NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsWindow::SetPreferredSize(PRInt32 aWidth,
+                                 PRInt32 aHeight)
+{
+    mPreferredWidth  = aWidth;
+    mPreferredHeight = aHeight;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::Enable(PRBool aState)
+{
+    mEnabled = aState;
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindow::IsEnabled(PRBool *aState)
+{
+    *aState = mEnabled;
+
+    return NS_OK;
+}
+
+void
+nsWindow::OnDestroy(void)
+{
+    if (mOnDestroyCalled)
+        return;
+
+    mOnDestroyCalled = PR_TRUE;
+
+    // release references to children, device context, toolkit + app shell
+    nsBaseWidget::OnDestroy();
+
+    // let go of our parent
+    mParent = nsnull;
+
+    nsCOMPtr<nsIWidget> kungFuDeathGrip = this;
+
+    nsGUIEvent event(PR_TRUE, NS_DESTROY, this);
+    nsEventStatus status;
+    DispatchEvent(&event, status);
+}
+
+PRBool
+nsWindow::AreBoundsSane(void)
+{
+    if (mBounds.width > 0 && mBounds.height > 0)
+        return PR_TRUE;
+
+    return PR_FALSE;
+}
new file mode 100644
--- /dev/null
+++ b/widget/src/qt/nsWindow.h
@@ -0,0 +1,428 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Christopher Blizzard
+ * <blizzard@mozilla.org>.  Portions created by the Initial Developer
+ * are Copyright (C) 2001 the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Masayuki Nakano <masayuki@d-toybox.com>
+ *   Vladimir Vukicevic <vladimir@pobox.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __nsWindow_h__
+#define __nsWindow_h__
+
+#include "nsAutoPtr.h"
+
+#include "nsBaseWidget.h"
+#include "nsGUIEvent.h"
+#include <QKeyEvent>
+
+#include "nsWeakReference.h"
+
+#include "nsIDragService.h"
+#include "nsITimer.h"
+#include "nsWidgetAtoms.h"
+
+
+#ifdef Q_WS_X11
+#include <QX11Info>
+#endif
+
+#ifdef MOZ_LOGGING
+
+// make sure that logging is enabled before including prlog.h
+#define FORCE_PR_LOG
+
+#include "prlog.h"
+
+extern PRLogModuleInfo *gWidgetLog;
+extern PRLogModuleInfo *gWidgetFocusLog;
+extern PRLogModuleInfo *gWidgetIMLog;
+extern PRLogModuleInfo *gWidgetDrawLog;
+
+#define LOG(args) PR_LOG(gWidgetLog, 4, args)
+#define LOGFOCUS(args) PR_LOG(gWidgetFocusLog, 4, args)
+#define LOGIM(args) PR_LOG(gWidgetIMLog, 4, args)
+#define LOGDRAW(args) PR_LOG(gWidgetDrawLog, 4, args)
+
+#else
+
+#ifdef DEBUG_WIDGETS
+
+#define PR_LOG2(_args)         \
+    PR_BEGIN_MACRO             \
+      qDebug _args;            \
+    PR_END_MACRO
+
+#define LOG(args) PR_LOG2(args)
+#define LOGFOCUS(args) PR_LOG2(args)
+#define LOGIM(args) PR_LOG2(args)
+#define LOGDRAW(args) PR_LOG2(args)
+
+#else
+
+#define LOG(args)
+#define LOGFOCUS(args)
+#define LOGIM(args)
+#define LOGDRAW(args)
+
+#endif
+
+#endif /* MOZ_LOGGING */
+
+class QEvent;
+
+class MozQWidget;
+
+class nsWindow : public nsBaseWidget,
+                 public nsSupportsWeakReference
+{
+public:
+    nsWindow();
+    virtual ~nsWindow();
+
+    static void ReleaseGlobals();
+
+    NS_DECL_ISUPPORTS_INHERITED
+
+    //
+    // nsIWidget
+    //
+
+    NS_IMETHOD         Create(nsIWidget        *aParent,
+                              const nsRect     &aRect,
+                              EVENT_CALLBACK   aHandleEventFunction,
+                              nsIDeviceContext *aContext,
+                              nsIAppShell      *aAppShell,
+                              nsIToolkit       *aToolkit,
+                              nsWidgetInitData *aInitData);
+    NS_IMETHOD         Create(nsNativeWidget aParent,
+                              const nsRect     &aRect,
+                              EVENT_CALLBACK   aHandleEventFunction,
+                              nsIDeviceContext *aContext,
+                              nsIAppShell      *aAppShell,
+                              nsIToolkit       *aToolkit,
+                              nsWidgetInitData *aInitData);
+    NS_IMETHOD         Destroy(void);
+    NS_IMETHOD         SetParent(nsIWidget* aNewParent);
+    virtual nsIWidget *GetParent(void);
+    NS_IMETHOD         Show(PRBool aState);
+    NS_IMETHOD         SetModal(PRBool aModal);
+    NS_IMETHOD         IsVisible(PRBool & aState);
+    NS_IMETHOD         ConstrainPosition(PRBool aAllowSlop,
+                                         PRInt32 *aX,
+                                         PRInt32 *aY);
+    NS_IMETHOD         Move(PRInt32 aX,
+                            PRInt32 aY);
+    NS_IMETHOD         Resize(PRInt32 aWidth,
+                              PRInt32 aHeight,
+                              PRBool  aRepaint);
+    NS_IMETHOD         Resize(PRInt32 aX,
+                              PRInt32 aY,
+                              PRInt32 aWidth,
+                              PRInt32 aHeight,
+                              PRBool   aRepaint);
+    NS_IMETHOD         SetZIndex(PRInt32 aZIndex);
+    NS_IMETHOD         PlaceBehind(nsTopLevelWidgetZPlacement  aPlacement,
+                                   nsIWidget                  *aWidget,
+                                   PRBool                      aActivate);
+    NS_IMETHOD         SetSizeMode(PRInt32 aMode);
+    NS_IMETHOD         Enable(PRBool aState);
+    NS_IMETHOD         SetFocus(PRBool aRaise = PR_FALSE);
+    NS_IMETHOD         GetScreenBounds(nsRect &aRect);
+    NS_IMETHOD         SetForegroundColor(const nscolor &aColor);
+    NS_IMETHOD         SetBackgroundColor(const nscolor &aColor);
+    NS_IMETHOD         SetCursor(nsCursor aCursor);
+    NS_IMETHOD         SetCursor(imgIContainer* aCursor,
+                                 PRUint32 aHotspotX, PRUint32 aHotspotY);
+    NS_IMETHOD         SetHasTransparentBackground(PRBool aTransparent);
+    NS_IMETHOD         GetHasTransparentBackground(PRBool& aTransparent);
+    NS_IMETHOD         HideWindowChrome(PRBool aShouldHide);
+    NS_IMETHOD         MakeFullScreen(PRBool aFullScreen);
+    NS_IMETHOD         Validate();
+    NS_IMETHOD         Invalidate(PRBool aIsSynchronous);
+    NS_IMETHOD         Invalidate(const nsRect &aRect,
+                                  PRBool        aIsSynchronous);
+    NS_IMETHOD         InvalidateRegion(const nsIRegion *aRegion,
+                                        PRBool           aIsSynchronous);
+    NS_IMETHOD         Update();
+    NS_IMETHOD         SetColorMap(nsColorMap *aColorMap);
+    NS_IMETHOD         Scroll(PRInt32  aDx,
+                              PRInt32  aDy,
+                              nsRect  *aClipRect);
+    NS_IMETHOD         ScrollWidgets(PRInt32 aDx,
+                                     PRInt32 aDy);
+    NS_IMETHOD         ScrollRect(nsRect  &aSrcRect,
+                                  PRInt32  aDx,
+                                  PRInt32  aDy);
+
+
+    NS_IMETHOD         PreCreateWidget(nsWidgetInitData *aWidgetInitData);
+
+    virtual void*      GetNativeData(PRUint32 aDataType);
+    NS_IMETHOD         SetBorderStyle(nsBorderStyle aBorderStyle);
+    NS_IMETHOD         SetTitle(const nsAString& aTitle);
+    NS_IMETHOD         SetIcon(const nsAString& aIconSpec);
+    NS_IMETHOD         SetMenuBar(void * aMenuBar) { return NS_ERROR_FAILURE; }
+    NS_IMETHOD         ShowMenuBar(PRBool aShow);
+    NS_IMETHOD         WidgetToScreen(const nsRect& aOldRect,
+                                      nsRect& aNewRect);
+    NS_IMETHOD         ScreenToWidget(const nsRect& aOldRect,
+                                      nsRect& aNewRect);
+    NS_IMETHOD         BeginResizingChildren(void);
+    NS_IMETHOD         EndResizingChildren(void);
+    NS_IMETHOD         GetPreferredSize (PRInt32 &aWidth,
+                                         PRInt32 &aHeight);
+    NS_IMETHOD         SetPreferredSize (PRInt32 aWidth,
+                                         PRInt32 aHeight);
+    NS_IMETHOD         DispatchEvent(nsGUIEvent *aEvent, nsEventStatus &aStatus);
+
+    NS_IMETHOD         EnableDragDrop(PRBool aEnable);
+    virtual void       ConvertToDeviceCoordinates(nscoord &aX,
+                                                  nscoord &aY);
+    NS_IMETHOD         CaptureMouse(PRBool aCapture);
+    NS_IMETHOD         CaptureRollupEvents(nsIRollupListener *aListener,
+                                           PRBool aDoCapture,
+                                           PRBool aConsumeRollupEvent);
+
+    NS_IMETHOD         SetWindowClass(const nsAString& xulWinType);
+
+    NS_IMETHOD         GetAttention(PRInt32 aCycleCount);
+    NS_IMETHOD         BeginResizeDrag   (nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical);
+
+    //
+    // utility methods
+    //
+
+    void               LoseFocus();
+    qint32             ConvertBorderStyles(nsBorderStyle aStyle);
+
+
+    /***** from CommonWidget *****/
+
+    // event handling code
+
+    void DispatchGotFocusEvent(void);
+    void DispatchLostFocusEvent(void);
+    void DispatchActivateEvent(void);
+    void DispatchDeactivateEvent(void);
+    void DispatchResizeEvent(nsRect &aRect, nsEventStatus &aStatus);
+
+    nsEventStatus DispatchEvent(nsGUIEvent *aEvent) {
+        nsEventStatus status;
+        DispatchEvent(aEvent, status);
+        return status;
+    }
+
+    // Some of the nsIWidget methods
+    NS_IMETHOD         IsEnabled        (PRBool *aState);
+
+    // called when we are destroyed
+    void OnDestroy(void);
+
+    // called to check and see if a widget's dimensions are sane
+    PRBool AreBoundsSane(void);
+
+protected:
+    nsCOMPtr<nsIWidget> mParent;
+    // Is this a toplevel window?
+    PRPackedBool        mIsTopLevel;
+    // Has this widget been destroyed yet?
+    PRPackedBool        mIsDestroyed;
+
+    // This flag tracks if we're hidden or shown.
+    PRPackedBool        mIsShown;
+    // is this widget enabled?
+    PRBool              mEnabled;
+    // Has anyone set an x/y location for this widget yet? Toplevels
+    // shouldn't be automatically set to 0,0 for first show.
+    PRBool              mPlaced;
+
+    // Preferred sizes
+    PRUint32            mPreferredWidth;
+    PRUint32            mPreferredHeight;
+
+    /**
+     * Event handlers (proxied from the actual qwidget).
+     * They follow normal Qt widget semantics.
+     */
+    void Initialize(QWidget *widget);
+    friend class nsQtEventDispatcher;
+    friend class InterceptContainer;
+    friend class MozQWidget;
+
+    virtual nsEventStatus OnPaintEvent(QPaintEvent *);
+    virtual nsEventStatus OnMoveEvent(QMoveEvent *);
+    virtual nsEventStatus OnResizeEvent(QResizeEvent *);
+    virtual nsEventStatus OnCloseEvent(QCloseEvent *);
+    virtual nsEventStatus OnEnterNotifyEvent(QEvent *);
+    virtual nsEventStatus OnLeaveNotifyEvent(QEvent *);
+    virtual nsEventStatus OnMotionNotifyEvent(QMouseEvent *);
+    virtual nsEventStatus OnButtonPressEvent(QMouseEvent *);
+    virtual nsEventStatus OnButtonReleaseEvent(QMouseEvent *);
+    virtual nsEventStatus mouseDoubleClickEvent(QMouseEvent *);
+    virtual nsEventStatus OnFocusInEvent(QFocusEvent *);
+    virtual nsEventStatus OnFocusOutEvent(QFocusEvent *);
+    virtual nsEventStatus OnKeyPressEvent(QKeyEvent *);
+    virtual nsEventStatus OnKeyReleaseEvent(QKeyEvent *);
+    virtual nsEventStatus OnScrollEvent(QWheelEvent *);
+
+    virtual nsEventStatus contextMenuEvent(QContextMenuEvent *);
+    virtual nsEventStatus imStartEvent(QEvent *);
+    virtual nsEventStatus imComposeEvent(QEvent *);
+    virtual nsEventStatus imEndEvent(QEvent *);
+    virtual nsEventStatus OnDragEnter (QDragEnterEvent *);
+    virtual nsEventStatus OnDragMotionEvent(QDragMoveEvent *);
+    virtual nsEventStatus OnDragLeaveEvent(QDragLeaveEvent *);
+    virtual nsEventStatus OnDragDropEvent (QDropEvent *);
+    virtual nsEventStatus showEvent(QShowEvent *);
+    virtual nsEventStatus hideEvent(QHideEvent *);
+
+    nsEventStatus         OnWindowStateEvent(QEvent *aEvent);
+
+    nsresult           NativeCreate(nsIWidget        *aParent,
+                                    nsNativeWidget    aNativeParent,
+                                    const nsRect     &aRect,
+                                    EVENT_CALLBACK    aHandleEventFunction,
+                                    nsIDeviceContext *aContext,
+                                    nsIAppShell      *aAppShell,
+                                    nsIToolkit       *aToolkit,
+                                    nsWidgetInitData *aInitData);
+
+    void               NativeResize(PRInt32 aWidth,
+                                    PRInt32 aHeight,
+                                    PRBool  aRepaint);
+
+    void               NativeResize(PRInt32 aX,
+                                    PRInt32 aY,
+                                    PRInt32 aWidth,
+                                    PRInt32 aHeight,
+                                    PRBool  aRepaint);
+
+    void               NativeShow  (PRBool  aAction);
+
+    enum PluginType {
+        PluginType_NONE = 0,   /* do not have any plugin */
+        PluginType_XEMBED,     /* the plugin support xembed */
+        PluginType_NONXEMBED   /* the plugin does not support xembed */
+    };
+
+    void               SetPluginType(PluginType aPluginType);
+    void               SetNonXEmbedPluginFocus(void);
+    void               LoseNonXEmbedPluginFocus(void);
+
+    void               ThemeChanged(void);
+
+   gfxASurface        *GetThebesSurface();
+
+private:
+    void               GetToplevelWidget(QWidget **aWidget);
+    void               SetUrgencyHint(QWidget *top_window, PRBool state);
+    void              *SetupPluginPort(void);
+    nsresult           SetWindowIconList(const nsCStringArray &aIconList);
+    void               SetDefaultIcon(void);
+    void               InitButtonEvent(nsMouseEvent &event, QMouseEvent *aEvent, int aClickCount = 1);
+    PRBool             DispatchCommandEvent(nsIAtom* aCommand);
+    QWidget           *createQWidget(QWidget *parent, nsWidgetInitData *aInitData);
+
+    QWidget            *mDrawingArea;
+    MozQWidget *mMozQWidget;
+
+    PRUint32            mIsVisible : 1,
+                        mActivatePending : 1;
+    PRInt32             mSizeState;
+    PluginType          mPluginType;
+
+    nsRefPtr<gfxASurface> mThebesSurface;
+
+    PRBool       mIsTransparent;
+ 
+    // all of our DND stuff
+    // this is the last window that had a drag event happen on it.
+    void   InitDragEvent         (nsMouseEvent &aEvent);
+
+    // this is everything we need to be able to fire motion events
+    // repeatedly
+    PRUint32 mKeyDownFlags[8];
+
+    /* Helper methods for DOM Key Down event suppression. */
+    PRUint32* GetFlagWord32(PRUint32 aKeyCode, PRUint32* aMask) {
+        /* Mozilla DOM Virtual Key Code is from 0 to 224. */
+        NS_ASSERTION((aKeyCode <= 0xFF), "Invalid DOM Key Code");
+        aKeyCode &= 0xFF;
+
+        /* 32 = 2^5 = 0x20 */
+        *aMask = PRUint32(1) << (aKeyCode & 0x1F);
+        return &mKeyDownFlags[(aKeyCode >> 5)];
+    }
+
+    PRBool IsKeyDown(PRUint32 aKeyCode) {
+        PRUint32 mask;
+        PRUint32* flag = GetFlagWord32(aKeyCode, &mask);
+        return ((*flag) & mask) != 0;
+    }
+
+    void SetKeyDownFlag(PRUint32 aKeyCode) {
+        PRUint32 mask;
+        PRUint32* flag = GetFlagWord32(aKeyCode, &mask);
+        *flag |= mask;
+    }
+
+    void ClearKeyDownFlag(PRUint32 aKeyCode) {
+        PRUint32 mask;
+        PRUint32* flag = GetFlagWord32(aKeyCode, &mask);
+        *flag &= ~mask;
+    }
+    PRInt32 mQCursor;
+
+};
+
+class nsChildWindow : public nsWindow
+{
+public:
+    nsChildWindow();
+    ~nsChildWindow();
+
+  PRInt32 mChildID;
+};
+
+class nsPopupWindow : public nsWindow
+{
+public:
+  nsPopupWindow ();
+  ~nsPopupWindow ();
+
+  PRInt32 mChildID;
+};
+#endif /* __nsWindow_h__ */
+
--- a/widget/src/xpwidgets/Makefile.in
+++ b/widget/src/xpwidgets/Makefile.in
@@ -82,22 +82,22 @@ CPPSRCS		= \
 		nsWidgetAtoms.cpp \
 		nsIdleService.cpp \
 		$(NULL)
 
 ifneq (,$(filter beos os2 cocoa windows,$(MOZ_WIDGET_TOOLKIT)))
 CPPSRCS += nsBaseClipboard.cpp
 endif
 
-ifneq (,$(filter beos gtk2 os2 cocoa photon windows,$(MOZ_WIDGET_TOOLKIT)))
+ifneq (,$(filter beos qt gtk2 os2 cocoa photon windows,$(MOZ_WIDGET_TOOLKIT)))
 CPPSRCS += nsBaseFilePicker.cpp
 REQUIRES += docshell view intl
 endif
 
-ifneq (,$(filter gtk2 windows cocoa,$(MOZ_WIDGET_TOOLKIT)))
+ifneq (,$(filter qt gtk2 windows cocoa,$(MOZ_WIDGET_TOOLKIT)))
 CPPSRCS += nsNativeTheme.cpp
 endif
 
 LOCAL_INCLUDES	= \
 		-I$(srcdir)/../$(MOZ_WIDGET_TOOLKIT) \
 		-I$(srcdir) \
 		$(NULL)