--- 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 <romaxa@gmail.com></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, ®ion);
+ _cairo_traps_fini (&traps);
+
+ if (status == CAIRO_INT_STATUS_SUCCESS) {
+ cairo_box_int_t *boxes;
+ int n_boxes;
+
+ QRegion qr;
+
+ _cairo_region_get_boxes (®ion, &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 (®ion, boxes);
+ _cairo_region_fini (®ion);
+
+ 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 (®ion, &rect);
+
+ _cairo_surface_set_clip_region (qs->xlib_equiv, ®ion, ++qs->xlib_clip_serial);
+
+ _cairo_region_fini (®ion);
+ }
+
+ 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▭
+ 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 = ▭ // 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 = ▭
+ // 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)