summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/gtk
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:30:52 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:30:52 -0800
commit8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2 (patch)
tree11425ea0b299d6fb89c6d3618a22d97d5bf68d0f /WebCore/platform/gtk
parent648161bb0edfc3d43db63caed5cc5213bc6cb78f (diff)
downloadexternal_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.zip
external_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.tar.gz
external_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'WebCore/platform/gtk')
-rw-r--r--WebCore/platform/gtk/ClipboardGtk.cpp127
-rw-r--r--WebCore/platform/gtk/ClipboardGtk.h69
-rw-r--r--WebCore/platform/gtk/ContextMenuGtk.cpp95
-rw-r--r--WebCore/platform/gtk/ContextMenuItemGtk.cpp253
-rw-r--r--WebCore/platform/gtk/CursorGtk.cpp341
-rw-r--r--WebCore/platform/gtk/CursorGtk.h221
-rw-r--r--WebCore/platform/gtk/DragDataGtk.cpp86
-rw-r--r--WebCore/platform/gtk/DragImageGtk.cpp54
-rw-r--r--WebCore/platform/gtk/EventLoopGtk.cpp32
-rw-r--r--WebCore/platform/gtk/FileChooserGtk.cpp70
-rw-r--r--WebCore/platform/gtk/FileSystemGtk.cpp267
-rw-r--r--WebCore/platform/gtk/KURLGtk.cpp40
-rw-r--r--WebCore/platform/gtk/KeyEventGtk.cpp550
-rw-r--r--WebCore/platform/gtk/KeyboardCodes.h543
-rw-r--r--WebCore/platform/gtk/Language.cpp60
-rw-r--r--WebCore/platform/gtk/LocalizedStringsGtk.cpp346
-rw-r--r--WebCore/platform/gtk/LoggingGtk.cpp32
-rw-r--r--WebCore/platform/gtk/MIMETypeRegistryGtk.cpp73
-rw-r--r--WebCore/platform/gtk/MouseEventGtk.cpp112
-rw-r--r--WebCore/platform/gtk/PasteboardGtk.cpp217
-rw-r--r--WebCore/platform/gtk/PasteboardHelper.h47
-rw-r--r--WebCore/platform/gtk/PlatformScreenGtk.cpp133
-rw-r--r--WebCore/platform/gtk/PopupMenuGtk.cpp160
-rw-r--r--WebCore/platform/gtk/RenderThemeGtk.cpp478
-rw-r--r--WebCore/platform/gtk/RenderThemeGtk.h128
-rw-r--r--WebCore/platform/gtk/ScrollViewGtk.cpp195
-rw-r--r--WebCore/platform/gtk/ScrollbarGtk.cpp150
-rw-r--r--WebCore/platform/gtk/ScrollbarGtk.h67
-rw-r--r--WebCore/platform/gtk/ScrollbarThemeGtk.cpp56
-rw-r--r--WebCore/platform/gtk/ScrollbarThemeGtk.h41
-rw-r--r--WebCore/platform/gtk/SearchPopupMenuGtk.cpp46
-rw-r--r--WebCore/platform/gtk/SharedBufferGtk.cpp53
-rw-r--r--WebCore/platform/gtk/SharedTimerGtk.cpp83
-rw-r--r--WebCore/platform/gtk/SoundGtk.cpp35
-rw-r--r--WebCore/platform/gtk/SystemTimeGtk.cpp32
-rw-r--r--WebCore/platform/gtk/SystemTimeLinux.cpp44
-rw-r--r--WebCore/platform/gtk/TemporaryLinkStubs.cpp68
-rw-r--r--WebCore/platform/gtk/WheelEventGtk.cpp79
-rw-r--r--WebCore/platform/gtk/WidgetGtk.cpp180
-rw-r--r--WebCore/platform/gtk/gtk2drawing.c3311
-rw-r--r--WebCore/platform/gtk/gtkdrawing.h428
-rw-r--r--WebCore/platform/gtk/guriescape.c219
-rw-r--r--WebCore/platform/gtk/guriescape.h44
43 files changed, 9665 insertions, 0 deletions
diff --git a/WebCore/platform/gtk/ClipboardGtk.cpp b/WebCore/platform/gtk/ClipboardGtk.cpp
new file mode 100644
index 0000000..44aa7f7
--- /dev/null
+++ b/WebCore/platform/gtk/ClipboardGtk.cpp
@@ -0,0 +1,127 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "ClipboardGtk.h"
+
+#include "NotImplemented.h"
+#include "StringHash.h"
+
+#include "Editor.h"
+
+namespace WebCore {
+
+PassRefPtr<Clipboard> Editor::newGeneralClipboard(ClipboardAccessPolicy policy)
+{
+ return ClipboardGtk::create(policy, false);
+}
+
+ClipboardGtk::ClipboardGtk(ClipboardAccessPolicy policy, bool forDragging)
+ : Clipboard(policy, forDragging)
+{
+ notImplemented();
+}
+
+ClipboardGtk::~ClipboardGtk()
+{
+ notImplemented();
+}
+
+void ClipboardGtk::clearData(const String&)
+{
+ notImplemented();
+}
+
+void ClipboardGtk::clearAllData()
+{
+ notImplemented();
+}
+
+String ClipboardGtk::getData(const String&, bool &success) const
+{
+ notImplemented();
+ success = false;
+ return String();
+}
+
+bool ClipboardGtk::setData(const String&, const String&)
+{
+ notImplemented();
+ return false;
+}
+
+HashSet<String> ClipboardGtk::types() const
+{
+ notImplemented();
+ return HashSet<String>();
+}
+
+IntPoint ClipboardGtk::dragLocation() const
+{
+ notImplemented();
+ return IntPoint(0, 0);
+}
+
+CachedImage* ClipboardGtk::dragImage() const
+{
+ notImplemented();
+ return 0;
+}
+
+void ClipboardGtk::setDragImage(CachedImage*, const IntPoint&)
+{
+ notImplemented();
+}
+
+Node* ClipboardGtk::dragImageElement()
+{
+ notImplemented();
+ return 0;
+}
+
+void ClipboardGtk::setDragImageElement(Node*, const IntPoint&)
+{
+ notImplemented();
+}
+
+DragImageRef ClipboardGtk::createDragImage(IntPoint&) const
+{
+ notImplemented();
+ return 0;
+}
+
+void ClipboardGtk::declareAndWriteDragImage(Element*, const KURL&, const String&, Frame*)
+{
+ notImplemented();
+}
+
+void ClipboardGtk::writeURL(const KURL&, const String&, Frame*)
+{
+ notImplemented();
+}
+
+void ClipboardGtk::writeRange(Range*, Frame*)
+{
+ notImplemented();
+}
+
+bool ClipboardGtk::hasData()
+{
+ notImplemented();
+ return false;
+}
+
+}
diff --git a/WebCore/platform/gtk/ClipboardGtk.h b/WebCore/platform/gtk/ClipboardGtk.h
new file mode 100644
index 0000000..b8b4ddf
--- /dev/null
+++ b/WebCore/platform/gtk/ClipboardGtk.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, Holger Hans Peter Freyther
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ClipboardGdk_h
+#define ClipboardGdk_h
+
+#include "Clipboard.h"
+
+namespace WebCore {
+ class CachedImage;
+
+ // State available during IE's events for drag and drop and copy/paste
+ // Created from the EventHandlerGtk to be used by the dom
+ class ClipboardGtk : public Clipboard {
+ public:
+ static PassRefPtr<ClipboardGtk> create(ClipboardAccessPolicy policy, bool isForDragging)
+ {
+ return adoptRef(new ClipboardGtk(policy, isForDragging));
+ }
+ virtual ~ClipboardGtk();
+
+ void clearData(const String&);
+ void clearAllData();
+ String getData(const String&, bool&) const;
+ bool setData(const String&, const String&);
+
+ HashSet<String> types() const;
+ IntPoint dragLocation() const;
+ CachedImage* dragImage() const;
+ void setDragImage(CachedImage*, const IntPoint&);
+ Node* dragImageElement();
+ void setDragImageElement(Node*, const IntPoint&);
+
+ virtual DragImageRef createDragImage(IntPoint&) const;
+ virtual void declareAndWriteDragImage(Element*, const KURL&, const String&, Frame*);
+ virtual void writeURL(const KURL&, const String&, Frame*);
+ virtual void writeRange(Range*, Frame*);
+
+ virtual bool hasData();
+
+ private:
+ ClipboardGtk(ClipboardAccessPolicy, bool);
+ };
+}
+
+#endif
diff --git a/WebCore/platform/gtk/ContextMenuGtk.cpp b/WebCore/platform/gtk/ContextMenuGtk.cpp
new file mode 100644
index 0000000..2365379
--- /dev/null
+++ b/WebCore/platform/gtk/ContextMenuGtk.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "ContextMenu.h"
+
+#include "ContextMenuController.h"
+
+#include <gtk/gtk.h>
+
+namespace WebCore {
+
+// TODO: ref-counting correctness checking.
+// See http://bugs.webkit.org/show_bug.cgi?id=16115
+
+static void menuItemActivated(GtkMenuItem* item, ContextMenuController* controller)
+{
+ ContextMenuItem contextItem(item);
+ controller->contextMenuItemSelected(&contextItem);
+}
+
+ContextMenu::ContextMenu(const HitTestResult& result)
+ : m_hitTestResult(result)
+{
+ m_platformDescription = GTK_MENU(gtk_menu_new());
+
+#if GLIB_CHECK_VERSION(2,10,0)
+ g_object_ref_sink(G_OBJECT(m_platformDescription));
+#else
+ g_object_ref(G_OBJECT(m_platformDescription));
+ gtk_object_sink(GTK_OBJECT(m_platformDescription));
+#endif
+}
+
+ContextMenu::~ContextMenu()
+{
+ if (m_platformDescription)
+ g_object_unref(m_platformDescription);
+}
+
+void ContextMenu::appendItem(ContextMenuItem& item)
+{
+ ASSERT(m_platformDescription);
+ checkOrEnableIfNeeded(item);
+
+ ContextMenuItemType type = item.type();
+ GtkMenuItem* platformItem = ContextMenuItem::createNativeMenuItem(item.releasePlatformDescription());
+ ASSERT(platformItem);
+
+ if (type == ActionType || type == CheckableActionType)
+ g_signal_connect(platformItem, "activate", G_CALLBACK(menuItemActivated), controller());
+
+ gtk_menu_shell_append(GTK_MENU_SHELL(m_platformDescription), GTK_WIDGET(platformItem));
+ gtk_widget_show(GTK_WIDGET(platformItem));
+}
+
+void ContextMenu::setPlatformDescription(PlatformMenuDescription menu)
+{
+ ASSERT(menu);
+ if (m_platformDescription)
+ g_object_unref(m_platformDescription);
+
+ m_platformDescription = menu;
+ g_object_ref(m_platformDescription);
+}
+
+PlatformMenuDescription ContextMenu::platformDescription() const
+{
+ return m_platformDescription;
+}
+
+PlatformMenuDescription ContextMenu::releasePlatformDescription()
+{
+ PlatformMenuDescription description = m_platformDescription;
+ m_platformDescription = 0;
+
+ return description;
+}
+
+}
diff --git a/WebCore/platform/gtk/ContextMenuItemGtk.cpp b/WebCore/platform/gtk/ContextMenuItemGtk.cpp
new file mode 100644
index 0000000..84f78c0
--- /dev/null
+++ b/WebCore/platform/gtk/ContextMenuItemGtk.cpp
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "ContextMenu.h"
+#include "ContextMenuItem.h"
+#include "CString.h"
+#include "NotImplemented.h"
+
+#include <gtk/gtk.h>
+
+#define WEBKIT_CONTEXT_MENU_ACTION "webkit-context-menu"
+
+namespace WebCore {
+
+static const char* gtkStockIDFromContextMenuAction(const ContextMenuAction& action)
+{
+ switch (action) {
+ case ContextMenuItemTagCopyLinkToClipboard:
+ case ContextMenuItemTagCopyImageToClipboard:
+ case ContextMenuItemTagCopy:
+ return GTK_STOCK_COPY;
+ case ContextMenuItemTagOpenLinkInNewWindow:
+ case ContextMenuItemTagOpenImageInNewWindow:
+ case ContextMenuItemTagOpenFrameInNewWindow:
+ return GTK_STOCK_OPEN;
+ case ContextMenuItemTagDownloadLinkToDisk:
+ case ContextMenuItemTagDownloadImageToDisk:
+ return GTK_STOCK_SAVE;
+ case ContextMenuItemTagGoBack:
+ return GTK_STOCK_GO_BACK;
+ case ContextMenuItemTagGoForward:
+ return GTK_STOCK_GO_FORWARD;
+ case ContextMenuItemTagStop:
+ return GTK_STOCK_STOP;
+ case ContextMenuItemTagReload:
+ return GTK_STOCK_REFRESH;
+ case ContextMenuItemTagCut:
+ return GTK_STOCK_CUT;
+ case ContextMenuItemTagPaste:
+ return GTK_STOCK_PASTE;
+ case ContextMenuItemTagDelete:
+ return GTK_STOCK_DELETE;
+#if GTK_CHECK_VERSION(2, 10, 0)
+ case ContextMenuItemTagSelectAll:
+ return GTK_STOCK_SELECT_ALL;
+#endif
+ case ContextMenuItemTagSpellingGuess:
+ return GTK_STOCK_INFO;
+ case ContextMenuItemTagIgnoreSpelling:
+ return GTK_STOCK_NO;
+ case ContextMenuItemTagLearnSpelling:
+ return GTK_STOCK_OK;
+ case ContextMenuItemTagOther:
+ return GTK_STOCK_MISSING_IMAGE;
+ case ContextMenuItemTagSearchInSpotlight:
+ return GTK_STOCK_FIND;
+ case ContextMenuItemTagSearchWeb:
+ return GTK_STOCK_FIND;
+ case ContextMenuItemTagOpenWithDefaultApplication:
+ return GTK_STOCK_OPEN;
+ case ContextMenuItemPDFZoomIn:
+ return GTK_STOCK_ZOOM_IN;
+ case ContextMenuItemPDFZoomOut:
+ return GTK_STOCK_ZOOM_OUT;
+ case ContextMenuItemPDFAutoSize:
+ return GTK_STOCK_ZOOM_FIT;
+ case ContextMenuItemPDFNextPage:
+ return GTK_STOCK_GO_FORWARD;
+ case ContextMenuItemPDFPreviousPage:
+ return GTK_STOCK_GO_BACK;
+ // New tags, not part of API
+ case ContextMenuItemTagOpenLink:
+ return GTK_STOCK_OPEN;
+ case ContextMenuItemTagCheckSpelling:
+ return GTK_STOCK_SPELL_CHECK;
+ case ContextMenuItemTagFontMenu:
+ return GTK_STOCK_SELECT_FONT;
+ case ContextMenuItemTagShowFonts:
+ return GTK_STOCK_SELECT_FONT;
+ case ContextMenuItemTagBold:
+ return GTK_STOCK_BOLD;
+ case ContextMenuItemTagItalic:
+ return GTK_STOCK_ITALIC;
+ case ContextMenuItemTagUnderline:
+ return GTK_STOCK_UNDERLINE;
+ case ContextMenuItemTagShowColors:
+ return GTK_STOCK_SELECT_COLOR;
+ default:
+ return NULL;
+ }
+}
+
+// Extract the ActionType from the menu item
+ContextMenuItem::ContextMenuItem(GtkMenuItem* item)
+ : m_platformDescription()
+{
+ if (GTK_IS_SEPARATOR_MENU_ITEM(item))
+ m_platformDescription.type = SeparatorType;
+ else if (gtk_menu_item_get_submenu(item))
+ m_platformDescription.type = SubmenuType;
+ else if (GTK_IS_CHECK_MENU_ITEM(item)) {
+ m_platformDescription.type = CheckableActionType;
+ m_platformDescription.checked = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item));
+ } else
+ m_platformDescription.type = ActionType;
+
+ m_platformDescription.action = *static_cast<ContextMenuAction*>(g_object_get_data(G_OBJECT(item), WEBKIT_CONTEXT_MENU_ACTION));
+
+ m_platformDescription.subMenu = GTK_MENU(gtk_menu_item_get_submenu(item));
+ if (m_platformDescription.subMenu)
+ g_object_ref(m_platformDescription.subMenu);
+}
+
+ContextMenuItem::ContextMenuItem(ContextMenu*)
+{
+ notImplemented();
+}
+
+ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, ContextMenu* subMenu)
+{
+ m_platformDescription.type = type;
+ m_platformDescription.action = action;
+ m_platformDescription.title = title;
+
+ setSubMenu(subMenu);
+}
+
+ContextMenuItem::~ContextMenuItem()
+{
+ if (m_platformDescription.subMenu)
+ g_object_unref(m_platformDescription.subMenu);
+}
+
+GtkMenuItem* ContextMenuItem::createNativeMenuItem(const PlatformMenuItemDescription& menu)
+{
+ GtkMenuItem* item = 0;
+ if (menu.type == SeparatorType)
+ item = GTK_MENU_ITEM(gtk_separator_menu_item_new());
+ else {
+ if (menu.type == CheckableActionType) {
+ item = GTK_MENU_ITEM(gtk_check_menu_item_new_with_mnemonic(menu.title.utf8().data()));
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), menu.checked);
+ } else {
+ if (const gchar* stockID = gtkStockIDFromContextMenuAction(menu.action)) {
+ item = GTK_MENU_ITEM(gtk_image_menu_item_new_with_mnemonic(menu.title.utf8().data()));
+ GtkWidget* image = gtk_image_new_from_stock(stockID, GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
+ } else
+ item = GTK_MENU_ITEM(gtk_menu_item_new_with_mnemonic(menu.title.utf8().data()));
+ }
+
+ ContextMenuAction* menuAction = static_cast<ContextMenuAction*>(malloc(sizeof(ContextMenuAction*)));
+ *menuAction = menu.action;
+ g_object_set_data(G_OBJECT(item), WEBKIT_CONTEXT_MENU_ACTION, menuAction);
+
+ gtk_widget_set_sensitive(GTK_WIDGET(item), menu.enabled);
+
+ if (menu.subMenu)
+ gtk_menu_item_set_submenu(item, GTK_WIDGET(menu.subMenu));
+ }
+
+ return item;
+}
+
+PlatformMenuItemDescription ContextMenuItem::releasePlatformDescription()
+{
+ PlatformMenuItemDescription description = m_platformDescription;
+ m_platformDescription = PlatformMenuItemDescription();
+ return description;
+}
+
+ContextMenuItemType ContextMenuItem::type() const
+{
+ return m_platformDescription.type;
+}
+
+void ContextMenuItem::setType(ContextMenuItemType type)
+{
+ m_platformDescription.type = type;
+}
+
+ContextMenuAction ContextMenuItem::action() const
+{
+ return m_platformDescription.action;
+}
+
+void ContextMenuItem::setAction(ContextMenuAction action)
+{
+ m_platformDescription.action = action;
+}
+
+String ContextMenuItem::title() const
+{
+ notImplemented();
+ return String();
+}
+
+void ContextMenuItem::setTitle(const String&)
+{
+ notImplemented();
+}
+
+PlatformMenuDescription ContextMenuItem::platformSubMenu() const
+{
+ return m_platformDescription.subMenu;
+}
+
+void ContextMenuItem::setSubMenu(ContextMenu* menu)
+{
+ if (m_platformDescription.subMenu)
+ g_object_unref(m_platformDescription.subMenu);
+
+ if (!menu)
+ return;
+
+ m_platformDescription.subMenu = menu->releasePlatformDescription();
+ m_platformDescription.type = SubmenuType;
+
+#if GLIB_CHECK_VERSION(2,10,0)
+ g_object_ref_sink(G_OBJECT(m_platformDescription.subMenu));
+#else
+ g_object_ref(G_OBJECT(m_platformDescription.subMenu));
+ gtk_object_sink(GTK_OBJECT(m_platformDescription.subMenu));
+#endif
+}
+
+void ContextMenuItem::setChecked(bool shouldCheck)
+{
+ m_platformDescription.checked = shouldCheck;
+}
+
+void ContextMenuItem::setEnabled(bool shouldEnable)
+{
+ m_platformDescription.enabled = shouldEnable;
+}
+
+}
diff --git a/WebCore/platform/gtk/CursorGtk.cpp b/WebCore/platform/gtk/CursorGtk.cpp
new file mode 100644
index 0000000..76f6d00
--- /dev/null
+++ b/WebCore/platform/gtk/CursorGtk.cpp
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2007 Christian Dywan <christian@twotoasts.de>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CursorGtk.h"
+
+#include "NotImplemented.h"
+#include <wtf/Assertions.h>
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+namespace WebCore {
+
+static GdkCursor* customCursorNew(CustomCursorType cursorType)
+{
+ CustomCursor cursor = CustomCursors[cursorType];
+ GdkCursor* c = gdk_cursor_new_from_name(gdk_display_get_default(), cursor.name);
+ if (!c) {
+ const GdkColor fg = { 0, 0, 0, 0 };
+ const GdkColor bg = { 65535, 65535, 65535, 65535 };
+
+ GdkPixmap* source = gdk_bitmap_create_from_data(NULL, cursor.bits, 32, 32);
+ GdkPixmap* mask = gdk_bitmap_create_from_data(NULL, cursor.mask_bits, 32, 32);
+ c = gdk_cursor_new_from_pixmap(source, mask, &fg, &bg, cursor.hot_x, cursor.hot_y);
+ g_object_unref(source);
+ g_object_unref(mask);
+ }
+ return c;
+}
+
+
+Cursor::Cursor(const Cursor& other)
+ : m_impl(other.m_impl)
+{
+ if (m_impl)
+ gdk_cursor_ref(m_impl);
+}
+
+Cursor::Cursor(Image*, const IntPoint&)
+{
+ notImplemented();
+}
+
+Cursor::~Cursor()
+{
+ if (m_impl)
+ gdk_cursor_unref(m_impl);
+}
+
+Cursor& Cursor::operator=(const Cursor& other)
+{
+ gdk_cursor_ref(other.m_impl);
+ gdk_cursor_unref(m_impl);
+ m_impl = other.m_impl;
+ return *this;
+}
+
+Cursor::Cursor(GdkCursor* c)
+ : m_impl(c)
+{
+ m_impl = c;
+ ASSERT(c);
+ gdk_cursor_ref(c);
+}
+
+const Cursor& pointerCursor()
+{
+ static Cursor c = gdk_cursor_new(GDK_LEFT_PTR);
+ return c;
+}
+
+const Cursor& crossCursor()
+{
+ static Cursor c = gdk_cursor_new(GDK_CROSS);
+ return c;
+}
+
+const Cursor& handCursor()
+{
+ static Cursor c = gdk_cursor_new(GDK_HAND2);
+ return c;
+}
+
+const Cursor& moveCursor()
+{
+ static Cursor c = gdk_cursor_new(GDK_FLEUR);
+ return c;
+}
+
+const Cursor& iBeamCursor()
+{
+ static Cursor c = gdk_cursor_new(GDK_XTERM);
+ return c;
+}
+
+const Cursor& waitCursor()
+{
+ static Cursor c = gdk_cursor_new(GDK_WATCH);
+ return c;
+}
+
+const Cursor& helpCursor()
+{
+ static Cursor c = gdk_cursor_new(GDK_QUESTION_ARROW);
+ return c;
+}
+
+const Cursor& eastResizeCursor()
+{
+ static Cursor c = gdk_cursor_new(GDK_RIGHT_SIDE);
+ return c;
+}
+
+const Cursor& northResizeCursor()
+{
+ static Cursor c = gdk_cursor_new(GDK_TOP_SIDE);
+ return c;
+}
+
+const Cursor& northEastResizeCursor()
+{
+ static Cursor c = gdk_cursor_new(GDK_TOP_RIGHT_CORNER);
+ return c;
+}
+
+const Cursor& northWestResizeCursor()
+{
+ static Cursor c = gdk_cursor_new(GDK_TOP_LEFT_CORNER);
+ return c;
+}
+
+const Cursor& southResizeCursor()
+{
+ static Cursor c = gdk_cursor_new(GDK_BOTTOM_SIDE);
+ return c;
+}
+
+const Cursor& southEastResizeCursor()
+{
+ static Cursor c = gdk_cursor_new(GDK_BOTTOM_RIGHT_CORNER);
+ return c;
+}
+
+const Cursor& southWestResizeCursor()
+{
+ static Cursor c = gdk_cursor_new(GDK_BOTTOM_LEFT_CORNER);
+ return c;
+}
+
+const Cursor& westResizeCursor()
+{
+ static Cursor c = gdk_cursor_new(GDK_LEFT_SIDE);
+ return c;
+}
+
+const Cursor& northSouthResizeCursor()
+{
+ static Cursor c = gdk_cursor_new(GDK_TOP_TEE);
+ return c;
+}
+
+const Cursor& eastWestResizeCursor()
+{
+ static Cursor c = gdk_cursor_new(GDK_LEFT_SIDE);
+ return c;
+}
+
+const Cursor& northEastSouthWestResizeCursor()
+{
+ static Cursor c = gdk_cursor_new(GDK_SIZING);
+ return c;
+}
+
+const Cursor& northWestSouthEastResizeCursor()
+{
+ static Cursor c = gdk_cursor_new(GDK_SIZING);
+ return c;
+}
+
+const Cursor& columnResizeCursor()
+{
+ static Cursor c = gdk_cursor_new(GDK_DOUBLE_ARROW);
+ return c;
+}
+
+const Cursor& rowResizeCursor()
+{
+ static Cursor c = gdk_cursor_new(GDK_DOUBLE_ARROW);
+ return c;
+}
+
+const Cursor& middlePanningCursor()
+{
+ return moveCursor();
+}
+
+const Cursor& eastPanningCursor()
+{
+ return eastResizeCursor();
+}
+
+const Cursor& northPanningCursor()
+{
+ return northResizeCursor();
+}
+
+const Cursor& northEastPanningCursor()
+{
+ return northEastResizeCursor();
+}
+
+const Cursor& northWestPanningCursor()
+{
+ return northWestResizeCursor();
+}
+
+const Cursor& southPanningCursor()
+{
+ return southResizeCursor();
+}
+
+const Cursor& southEastPanningCursor()
+{
+ return southEastResizeCursor();
+}
+
+const Cursor& southWestPanningCursor()
+{
+ return southWestResizeCursor();
+}
+
+const Cursor& westPanningCursor()
+{
+ return westResizeCursor();
+}
+
+
+const Cursor& verticalTextCursor()
+{
+ static Cursor c = customCursorNew(CustomCursorVerticalText);
+ return c;
+}
+
+const Cursor& cellCursor()
+{
+ notImplemented();
+ return pointerCursor();
+}
+
+const Cursor& contextMenuCursor()
+{
+ static Cursor c = customCursorNew(CustomCursorContextMenu);
+ return c;
+}
+
+const Cursor& noDropCursor()
+{
+ notImplemented();
+ return pointerCursor();
+}
+
+const Cursor& copyCursor()
+{
+ static Cursor c = customCursorNew(CustomCursorCopy);
+ return c;
+}
+
+const Cursor& progressCursor()
+{
+ notImplemented();
+ return pointerCursor();
+}
+
+const Cursor& aliasCursor()
+{
+ static Cursor c = customCursorNew(CustomCursorAlias);
+ return c;
+}
+
+const Cursor& noneCursor()
+{
+ notImplemented();
+ return pointerCursor();
+}
+
+const Cursor& notAllowedCursor()
+{
+ notImplemented();
+ return pointerCursor();
+}
+
+const Cursor& zoomInCursor()
+{
+ static Cursor c = customCursorNew(CustomCursorZoomIn);
+ return c;
+}
+
+const Cursor& zoomOutCursor()
+{
+ static Cursor c = customCursorNew(CustomCursorZoomOut);
+ return c;
+}
+
+const Cursor& grabCursor()
+{
+ notImplemented();
+ return pointerCursor();
+}
+
+const Cursor& grabbingCursor()
+{
+ notImplemented();
+ return pointerCursor();
+}
+
+}
diff --git a/WebCore/platform/gtk/CursorGtk.h b/WebCore/platform/gtk/CursorGtk.h
new file mode 100644
index 0000000..73f05a9
--- /dev/null
+++ b/WebCore/platform/gtk/CursorGtk.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2001 Tim Copperfield <timecop@network.email.ne.jp>
+ * Copyright (C) 2007 Christian Dywan <christian@twotoasts.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef CursorGtk_h
+#define CursorGtk_h
+
+#include "Cursor.h"
+
+/*
+ These cursors are copied from Mozilla code:
+ http://lxr.mozilla.org/mozilla1.8/source/widget/src/gtk2/nsGtkCursors.h
+*/
+
+/* MOZ_CURSOR_VERTICAL_TEXT */
+static const char moz_vertical_text_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
+ 0x06, 0x60, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00,
+ 0x02, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+static const char moz_vertical_text_mask_bits[] = {
+ 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
+ 0x0f, 0xf0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+/* MOZ_CURSOR_CONTEXT_MENU */
+static const char moz_menu_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+ 0x7c, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfc, 0xfd, 0x00, 0x00,
+ 0xfc, 0xff, 0x00, 0x00, 0x7c, 0x84, 0x00, 0x00, 0x6c, 0xfc, 0x00, 0x00,
+ 0xc4, 0x84, 0x00, 0x00, 0xc0, 0xfc, 0x00, 0x00, 0x80, 0x85, 0x00, 0x00,
+ 0x80, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+static const char moz_menu_mask_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x1e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
+ 0xfe, 0x00, 0x00, 0x00, 0xfe, 0xfd, 0x00, 0x00, 0xfe, 0xff, 0x01, 0x00,
+ 0xfe, 0xff, 0x01, 0x00, 0xfe, 0xff, 0x01, 0x00, 0xfe, 0xfe, 0x01, 0x00,
+ 0xee, 0xff, 0x01, 0x00, 0xe4, 0xff, 0x01, 0x00, 0xc0, 0xff, 0x01, 0x00,
+ 0xc0, 0xff, 0x01, 0x00, 0x80, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+/* MOZ_CURSOR_COPY */
+static const char moz_copy_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+ 0x7c, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00,
+ 0xfc, 0x03, 0x00, 0x00, 0x7c, 0x30, 0x00, 0x00, 0x6c, 0x30, 0x00, 0x00,
+ 0xc4, 0xfc, 0x00, 0x00, 0xc0, 0xfc, 0x00, 0x00, 0x80, 0x31, 0x00, 0x00,
+ 0x80, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+static const char moz_copy_mask_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x1e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
+ 0xfe, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x00,
+ 0xfe, 0x37, 0x00, 0x00, 0xfe, 0x7b, 0x00, 0x00, 0xfe, 0xfc, 0x00, 0x00,
+ 0xee, 0xff, 0x01, 0x00, 0xe4, 0xff, 0x01, 0x00, 0xc0, 0xff, 0x00, 0x00,
+ 0xc0, 0x7b, 0x00, 0x00, 0x80, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+/* MOZ_CURSOR_ALIAS */
+static const char moz_alias_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+ 0x7c, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00,
+ 0xfc, 0x03, 0x00, 0x00, 0x7c, 0xf0, 0x00, 0x00, 0x6c, 0xe0, 0x00, 0x00,
+ 0xc4, 0xf0, 0x00, 0x00, 0xc0, 0xb0, 0x00, 0x00, 0x80, 0x19, 0x00, 0x00,
+ 0x80, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+static const char moz_alias_mask_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x1e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
+ 0xfe, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x00,
+ 0xfe, 0xf7, 0x00, 0x00, 0xfe, 0xfb, 0x01, 0x00, 0xfe, 0xf0, 0x01, 0x00,
+ 0xee, 0xf9, 0x01, 0x00, 0xe4, 0xf9, 0x01, 0x00, 0xc0, 0xbf, 0x00, 0x00,
+ 0xc0, 0x3f, 0x00, 0x00, 0x80, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+/* MOZ_CURSOR_ZOOM_IN */
+static const char moz_zoom_in_bits[] = {
+ 0xf0, 0x00, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00,
+ 0x62, 0x04, 0x00, 0x00, 0x61, 0x08, 0x00, 0x00, 0xf9, 0x09, 0x00, 0x00,
+ 0xf9, 0x09, 0x00, 0x00, 0x61, 0x08, 0x00, 0x00, 0x62, 0x04, 0x00, 0x00,
+ 0x02, 0x04, 0x00, 0x00, 0x0c, 0x0f, 0x00, 0x00, 0xf0, 0x1c, 0x00, 0x00,
+ 0x00, 0x38, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+static const char moz_zoom_in_mask_bits[] = {
+ 0xf0, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x00,
+ 0xfe, 0x07, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00,
+ 0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x00,
+ 0xfe, 0x07, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0xf0, 0x1c, 0x00, 0x00,
+ 0x00, 0x38, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+/* MOZ_CURSOR_ZOOM_OUT */
+static const char moz_zoom_out_bits[] = {
+ 0xf0, 0x00, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00,
+ 0x02, 0x04, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xf9, 0x09, 0x00, 0x00,
+ 0xf9, 0x09, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00,
+ 0x02, 0x04, 0x00, 0x00, 0x0c, 0x0f, 0x00, 0x00, 0xf0, 0x1c, 0x00, 0x00,
+ 0x00, 0x38, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+static const char moz_zoom_out_mask_bits[] = {
+ 0xf0, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x00,
+ 0xfe, 0x07, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00,
+ 0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x00,
+ 0xfe, 0x07, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0xf0, 0x1c, 0x00, 0x00,
+ 0x00, 0x38, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+enum CustomCursorType {
+ CustomCursorCopy = 0,
+ CustomCursorAlias,
+ CustomCursorContextMenu,
+ CustomCursorZoomIn,
+ CustomCursorZoomOut,
+ CustomCursorVerticalText
+} ;
+
+typedef struct {
+ const char* name;
+ const char* bits;
+ const char* mask_bits;
+ int hot_x;
+ int hot_y;
+} CustomCursor;
+
+// create custom pixmap cursor from cursors in nsGTKCursorData.h
+static const CustomCursor CustomCursors[] = {
+ { "copy", moz_copy_bits, moz_copy_mask_bits, 2, 2 },
+ { "alias", moz_alias_bits, moz_alias_mask_bits, 2, 2 },
+ { "context-menu", moz_menu_bits, moz_menu_mask_bits, 2, 2 },
+ { "zoom-in", moz_zoom_in_bits, moz_zoom_in_mask_bits, 6, 6 },
+ { "zoom-out", moz_zoom_out_bits, moz_zoom_out_mask_bits, 6, 6 },
+ { "vertical-text", moz_vertical_text_bits, moz_vertical_text_mask_bits, 8, 4 },
+};
+
+#endif // CursorGtk_h
diff --git a/WebCore/platform/gtk/DragDataGtk.cpp b/WebCore/platform/gtk/DragDataGtk.cpp
new file mode 100644
index 0000000..69b3161
--- /dev/null
+++ b/WebCore/platform/gtk/DragDataGtk.cpp
@@ -0,0 +1,86 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "DragData.h"
+
+#include "Clipboard.h"
+#include "Document.h"
+#include "DocumentFragment.h"
+
+namespace WebCore {
+
+bool DragData::canSmartReplace() const
+{
+ return false;
+}
+
+bool DragData::containsColor() const
+{
+ return false;
+}
+
+bool DragData::containsFiles() const
+{
+ return false;
+}
+
+void DragData::asFilenames(Vector<String>& result) const
+{
+}
+
+bool DragData::containsPlainText() const
+{
+ return false;
+}
+
+String DragData::asPlainText() const
+{
+ return String();
+}
+
+Color DragData::asColor() const
+{
+ return Color();
+}
+
+PassRefPtr<Clipboard> DragData::createClipboard(ClipboardAccessPolicy) const
+{
+ return 0;
+}
+
+bool DragData::containsCompatibleContent() const
+{
+ return false;
+}
+
+bool DragData::containsURL() const
+{
+ return false;
+}
+
+String DragData::asURL(String* title) const
+{
+ return String();
+}
+
+
+PassRefPtr<DocumentFragment> DragData::asFragment(Document*) const
+{
+ return 0;
+}
+
+}
diff --git a/WebCore/platform/gtk/DragImageGtk.cpp b/WebCore/platform/gtk/DragImageGtk.cpp
new file mode 100644
index 0000000..4ddae3a
--- /dev/null
+++ b/WebCore/platform/gtk/DragImageGtk.cpp
@@ -0,0 +1,54 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "DragImage.h"
+
+#include "CachedImage.h"
+#include "Image.h"
+
+namespace WebCore {
+
+IntSize dragImageSize(DragImageRef)
+{
+ return IntSize(0, 0);
+}
+
+void deleteDragImage(DragImageRef)
+{
+}
+
+DragImageRef scaleDragImage(DragImageRef image, FloatSize)
+{
+ return image;
+}
+
+DragImageRef dissolveDragImageToFraction(DragImageRef image, float)
+{
+ return image;
+}
+
+DragImageRef createDragImageFromImage(Image*)
+{
+ return 0;
+}
+
+DragImageRef createDragImageIconForCachedImage(CachedImage*)
+{
+ return 0;
+}
+
+}
diff --git a/WebCore/platform/gtk/EventLoopGtk.cpp b/WebCore/platform/gtk/EventLoopGtk.cpp
new file mode 100644
index 0000000..4ef7b5c
--- /dev/null
+++ b/WebCore/platform/gtk/EventLoopGtk.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2008 Nuanti Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "EventLoop.h"
+
+#include <glib.h>
+
+namespace WebCore {
+
+void EventLoop::cycle()
+{
+ g_main_context_iteration(NULL, FALSE);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/gtk/FileChooserGtk.cpp b/WebCore/platform/gtk/FileChooserGtk.cpp
new file mode 100644
index 0000000..e984718
--- /dev/null
+++ b/WebCore/platform/gtk/FileChooserGtk.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FileChooser.h"
+
+#include "CString.h"
+#include "FileSystem.h"
+#include "Icon.h"
+#include "LocalizedStrings.h"
+#include "StringTruncator.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+namespace WebCore {
+
+static bool stringByAdoptingFileSystemRepresentation(gchar* systemFilename, String& result)
+{
+ if (!systemFilename)
+ return false;
+
+ result = filenameToString(systemFilename);
+ g_free(systemFilename);
+
+ return true;
+}
+
+String FileChooser::basenameForWidth(const Font& font, int width) const
+{
+ if (width <= 0)
+ return String();
+
+ String string = fileButtonNoFileSelectedLabel();
+
+ if (m_filenames.size() == 1) {
+ gchar* systemFilename = filenameFromString(m_filenames[0]);
+ gchar* systemBasename = g_path_get_basename(systemFilename);
+ g_free(systemFilename);
+ stringByAdoptingFileSystemRepresentation(systemBasename, string);
+ } else if (m_filenames.size() > 1)
+ return StringTruncator::rightTruncate(multipleFileUploadText(m_filenames.size()), width, font, false);
+
+ return StringTruncator::centerTruncate(string, width, font, false);
+}
+}
diff --git a/WebCore/platform/gtk/FileSystemGtk.cpp b/WebCore/platform/gtk/FileSystemGtk.cpp
new file mode 100644
index 0000000..965cea9
--- /dev/null
+++ b/WebCore/platform/gtk/FileSystemGtk.cpp
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ * Copyright (C) 2008 Collabora, Ltd.
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "FileSystem.h"
+
+#include "guriescape.h"
+#include "NotImplemented.h"
+#include "PlatformString.h"
+#include "CString.h"
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib/gutils.h>
+
+#include <unistd.h>
+
+namespace WebCore {
+
+/* On linux file names are just raw bytes, so also strings that cannot be encoded in any way
+ * are valid file names. This mean that we cannot just store a file name as-is in a String
+ * but we have to escape it.
+ * On Windows the GLib file name encoding is always UTF-8 so we can optimize this case. */
+String filenameToString(const char* filename)
+{
+ if (!filename)
+ return String();
+
+#if PLATFORM(WIN_OS)
+ return String::fromUTF8(filename);
+#else
+ gchar* escapedString = g_uri_escape_string(filename, "/:", false);
+ String string(escapedString);
+ g_free(escapedString);
+ return string;
+#endif
+}
+
+char* filenameFromString(const String& string)
+{
+#if PLATFORM(WIN_OS)
+ return g_strdup(string.utf8().data());
+#else
+ return g_uri_unescape_string(string.utf8().data(), 0);
+#endif
+}
+
+// Converts a string to something suitable to be displayed to the user.
+String filenameForDisplay(const String& string)
+{
+#if PLATFORM(WIN_OS)
+ return string;
+#else
+ gchar* filename = filenameFromString(string);
+ gchar* display = g_filename_to_utf8(filename, 0, 0, 0, 0);
+ g_free(filename);
+ if (!display)
+ return string;
+
+ String displayString = String::fromUTF8(display);
+ g_free(display);
+
+ return displayString;
+#endif
+}
+
+bool fileExists(const String& path)
+{
+ bool result = false;
+ gchar* filename = filenameFromString(path);
+
+ if (filename) {
+ result = g_file_test(filename, G_FILE_TEST_EXISTS);
+ g_free(filename);
+ }
+
+ return result;
+}
+
+bool deleteFile(const String& path)
+{
+ bool result = false;
+ gchar* filename = filenameFromString(path);
+
+ if (filename) {
+ result = g_remove(filename) == 0;
+ g_free(filename);
+ }
+
+ return result;
+}
+
+bool deleteEmptyDirectory(const String& path)
+{
+ bool result = false;
+ gchar* filename = filenameFromString(path);
+
+ if (filename) {
+ result = g_rmdir(filename) == 0;
+ g_free(filename);
+ }
+
+ return result;
+}
+
+bool getFileSize(const String& path, long long& resultSize)
+{
+ gchar* filename = filenameFromString(path);
+ if (!filename)
+ return false;
+
+ struct stat statResult;
+ gint result = g_stat(filename, &statResult);
+ g_free(filename);
+ if (result != 0)
+ return false;
+
+ resultSize = statResult.st_size;
+ return true;
+}
+
+bool getFileModificationTime(const String& path, time_t& modifiedTime)
+{
+ gchar* filename = filenameFromString(path);
+ if (!filename)
+ return false;
+
+ struct stat statResult;
+ gint result = g_stat(filename, &statResult);
+ g_free(filename);
+ if (result != 0)
+ return false;
+
+ modifiedTime = statResult.st_mtime;
+ return true;
+
+}
+
+String pathByAppendingComponent(const String& path, const String& component)
+{
+ if (path.endsWith(G_DIR_SEPARATOR_S))
+ return path + component;
+ else
+ return path + G_DIR_SEPARATOR_S + component;
+}
+
+bool makeAllDirectories(const String& path)
+{
+ gchar* filename = filenameFromString(path);
+ if (!filename)
+ return false;
+
+ gint result = g_mkdir_with_parents(filename, S_IRWXU);
+ g_free(filename);
+
+ return result == 0;
+}
+
+String homeDirectoryPath()
+{
+ return filenameToString(g_get_home_dir());
+}
+
+String pathGetFileName(const String& pathName)
+{
+ char* tmpFilename = filenameFromString(pathName);
+ char* baseName = g_path_get_basename(tmpFilename);
+ String fileName = String::fromUTF8(baseName);
+ g_free(baseName);
+ g_free(tmpFilename);
+
+ return fileName;
+}
+
+String directoryName(const String& path)
+{
+ notImplemented();
+ return String();
+}
+
+Vector<String> listDirectory(const String& path, const String& filter)
+{
+ Vector<String> entries;
+
+ gchar* filename = filenameFromString(path);
+ GDir* dir = g_dir_open(filename, 0, 0);
+ if (!dir)
+ return entries;
+
+ GPatternSpec *pspec = g_pattern_spec_new((filter.utf8()).data());
+ while (const char* name = g_dir_read_name(dir)) {
+ if (!g_pattern_match_string(pspec, name))
+ continue;
+
+ gchar* entry = g_build_filename(filename, name, NULL);
+ entries.append(filenameToString(entry));
+ g_free(entry);
+ }
+ g_dir_close(dir);
+ g_free(filename);
+
+ return entries;
+}
+
+CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle)
+{
+ gchar* filename = g_strdup_printf("%sXXXXXX", prefix);
+ gchar* tempPath = g_build_filename(g_get_tmp_dir(), filename, NULL);
+ g_free(filename);
+
+ int fileDescriptor = g_mkstemp(tempPath);
+ if (!isHandleValid(fileDescriptor)) {
+ LOG_ERROR("Can't create a temporary file.");
+ g_free(tempPath);
+ return 0;
+ }
+ CString tempFilePath = tempPath;
+ g_free(tempPath);
+
+ handle = fileDescriptor;
+ return tempFilePath;
+}
+
+void closeFile(PlatformFileHandle& handle)
+{
+ if (isHandleValid(handle)) {
+ close(handle);
+ handle = invalidPlatformFileHandle;
+ }
+}
+
+int writeToFile(PlatformFileHandle handle, const char* data, int length)
+{
+ int totalBytesWritten = 0;
+ while (totalBytesWritten < length) {
+ int bytesWritten = write(handle, data, length - totalBytesWritten);
+ if (bytesWritten < 0)
+ return -1;
+ totalBytesWritten += bytesWritten;
+ }
+
+ return totalBytesWritten;
+}
+
+bool unloadModule(PlatformModule module)
+{
+ return g_module_close(module);
+}
+}
diff --git a/WebCore/platform/gtk/KURLGtk.cpp b/WebCore/platform/gtk/KURLGtk.cpp
new file mode 100644
index 0000000..4858d3e
--- /dev/null
+++ b/WebCore/platform/gtk/KURLGtk.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2008 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "KURL.h"
+
+#include "CString.h"
+#include "FileSystem.h"
+
+#include <glib.h>
+
+namespace WebCore {
+
+String KURL::fileSystemPath() const
+{
+ gchar* filename = g_filename_from_uri(m_string.utf8().data(), 0, 0);
+ if (!filename)
+ return String();
+
+ String path = filenameToString(filename);
+ g_free(filename);
+ return path;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/gtk/KeyEventGtk.cpp b/WebCore/platform/gtk/KeyEventGtk.cpp
new file mode 100644
index 0000000..153ef19
--- /dev/null
+++ b/WebCore/platform/gtk/KeyEventGtk.cpp
@@ -0,0 +1,550 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ * Copyright (C) 2008 Collabora, Ltd. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PlatformKeyboardEvent.h"
+
+#include "KeyboardCodes.h"
+#include "NotImplemented.h"
+#include "TextEncoding.h"
+
+#include <gdk/gdk.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtkversion.h>
+
+namespace WebCore {
+
+// FIXME: This is incomplete. We should change this to mirror
+// more like what Firefox does, and generate these switch statements
+// at build time.
+static String keyIdentifierForGdkKeyCode(guint keyCode)
+{
+ switch (keyCode) {
+ case GDK_Menu:
+ case GDK_Alt_L:
+ case GDK_Alt_R:
+ return "Alt";
+ case GDK_Clear:
+ return "Clear";
+ case GDK_Down:
+ return "Down";
+ // "End"
+ case GDK_End:
+ return "End";
+ // "Enter"
+ case GDK_ISO_Enter:
+ case GDK_KP_Enter:
+ case GDK_Return:
+ return "Enter";
+ case GDK_Execute:
+ return "Execute";
+ case GDK_F1:
+ return "F1";
+ case GDK_F2:
+ return "F2";
+ case GDK_F3:
+ return "F3";
+ case GDK_F4:
+ return "F4";
+ case GDK_F5:
+ return "F5";
+ case GDK_F6:
+ return "F6";
+ case GDK_F7:
+ return "F7";
+ case GDK_F8:
+ return "F8";
+ case GDK_F9:
+ return "F9";
+ case GDK_F10:
+ return "F10";
+ case GDK_F11:
+ return "F11";
+ case GDK_F12:
+ return "F12";
+ case GDK_F13:
+ return "F13";
+ case GDK_F14:
+ return "F14";
+ case GDK_F15:
+ return "F15";
+ case GDK_F16:
+ return "F16";
+ case GDK_F17:
+ return "F17";
+ case GDK_F18:
+ return "F18";
+ case GDK_F19:
+ return "F19";
+ case GDK_F20:
+ return "F20";
+ case GDK_F21:
+ return "F21";
+ case GDK_F22:
+ return "F22";
+ case GDK_F23:
+ return "F23";
+ case GDK_F24:
+ return "F24";
+ case GDK_Help:
+ return "Help";
+ case GDK_Home:
+ return "Home";
+ case GDK_Insert:
+ return "Insert";
+ case GDK_Left:
+ return "Left";
+ case GDK_Page_Down:
+ return "PageDown";
+ case GDK_Page_Up:
+ return "PageUp";
+ case GDK_Pause:
+ return "Pause";
+ case GDK_3270_PrintScreen:
+ return "PrintScreen";
+ case GDK_Right:
+ return "Right";
+ case GDK_Select:
+ return "Select";
+ case GDK_Up:
+ return "Up";
+ // Standard says that DEL becomes U+007F.
+ case GDK_Delete:
+ return "U+007F";
+ case GDK_ISO_Left_Tab:
+ case GDK_3270_BackTab:
+ case GDK_Tab:
+ return "U+0009";
+ default:
+ return String::format("U+%04X", gdk_keyval_to_unicode(gdk_keyval_to_upper(keyCode)));
+ }
+}
+
+static int windowsKeyCodeForKeyEvent(unsigned int keycode)
+{
+ switch (keycode) {
+ case GDK_KP_0:
+ return VK_NUMPAD0;// (60) Numeric keypad 0 key
+ case GDK_KP_1:
+ return VK_NUMPAD1;// (61) Numeric keypad 1 key
+ case GDK_KP_2:
+ return VK_NUMPAD2; // (62) Numeric keypad 2 key
+ case GDK_KP_3:
+ return VK_NUMPAD3; // (63) Numeric keypad 3 key
+ case GDK_KP_4:
+ return VK_NUMPAD4; // (64) Numeric keypad 4 key
+ case GDK_KP_5:
+ return VK_NUMPAD5; //(65) Numeric keypad 5 key
+ case GDK_KP_6:
+ return VK_NUMPAD6; // (66) Numeric keypad 6 key
+ case GDK_KP_7:
+ return VK_NUMPAD7; // (67) Numeric keypad 7 key
+ case GDK_KP_8:
+ return VK_NUMPAD8; // (68) Numeric keypad 8 key
+ case GDK_KP_9:
+ return VK_NUMPAD9; // (69) Numeric keypad 9 key
+ case GDK_KP_Multiply:
+ return VK_MULTIPLY; // (6A) Multiply key
+ case GDK_KP_Add:
+ return VK_ADD; // (6B) Add key
+ case GDK_KP_Subtract:
+ return VK_SUBTRACT; // (6D) Subtract key
+ case GDK_KP_Decimal:
+ return VK_DECIMAL; // (6E) Decimal key
+ case GDK_KP_Divide:
+ return VK_DIVIDE; // (6F) Divide key
+
+ case GDK_BackSpace:
+ return VK_BACK; // (08) BACKSPACE key
+ case GDK_ISO_Left_Tab:
+ case GDK_3270_BackTab:
+ case GDK_Tab:
+ return VK_TAB; // (09) TAB key
+ case GDK_Clear:
+ return VK_CLEAR; // (0C) CLEAR key
+ case GDK_ISO_Enter:
+ case GDK_KP_Enter:
+ case GDK_Return:
+ return VK_RETURN; //(0D) Return key
+ case GDK_Shift_L:
+ case GDK_Shift_R:
+ return VK_SHIFT; // (10) SHIFT key
+ case GDK_Control_L:
+ case GDK_Control_R:
+ return VK_CONTROL; // (11) CTRL key
+ case GDK_Menu:
+ case GDK_Alt_L:
+ case GDK_Alt_R:
+ return VK_MENU; // (12) ALT key
+
+ case GDK_Pause:
+ return VK_PAUSE; // (13) PAUSE key
+ case GDK_Caps_Lock:
+ return VK_CAPITAL; // (14) CAPS LOCK key
+ case GDK_Kana_Lock:
+ case GDK_Kana_Shift:
+ return VK_KANA; // (15) Input Method Editor (IME) Kana mode
+ case GDK_Hangul:
+ return VK_HANGUL; // VK_HANGUL (15) IME Hangul mode
+ // VK_JUNJA (17) IME Junja mode
+ // VK_FINAL (18) IME final mode
+ case GDK_Hangul_Hanja:
+ return VK_HANJA; // (19) IME Hanja mode
+ case GDK_Kanji:
+ return VK_KANJI; // (19) IME Kanji mode
+ case GDK_Escape:
+ return VK_ESCAPE; // (1B) ESC key
+ // VK_CONVERT (1C) IME convert
+ // VK_NONCONVERT (1D) IME nonconvert
+ // VK_ACCEPT (1E) IME accept
+ // VK_MODECHANGE (1F) IME mode change request
+ case GDK_space:
+ return VK_SPACE; // (20) SPACEBAR
+ case GDK_Page_Up:
+ return VK_PRIOR; // (21) PAGE UP key
+ case GDK_Page_Down:
+ return VK_NEXT; // (22) PAGE DOWN key
+ case GDK_End:
+ return VK_END; // (23) END key
+ case GDK_Home:
+ return VK_HOME; // (24) HOME key
+ case GDK_Left:
+ return VK_LEFT; // (25) LEFT ARROW key
+ case GDK_Up:
+ return VK_UP; // (26) UP ARROW key
+ case GDK_Right:
+ return VK_RIGHT; // (27) RIGHT ARROW key
+ case GDK_Down:
+ return VK_DOWN; // (28) DOWN ARROW key
+ case GDK_Select:
+ return VK_SELECT; // (29) SELECT key
+ case GDK_Print:
+ return VK_PRINT; // (2A) PRINT key
+ case GDK_Execute:
+ return VK_EXECUTE;// (2B) EXECUTE key
+ //dunno on this
+ //case GDK_PrintScreen:
+ // return VK_SNAPSHOT; // (2C) PRINT SCREEN key
+ case GDK_Insert:
+ return VK_INSERT; // (2D) INS key
+ case GDK_Delete:
+ return VK_DELETE; // (2E) DEL key
+ case GDK_Help:
+ return VK_HELP; // (2F) HELP key
+ case GDK_0:
+ case GDK_parenleft:
+ return VK_0; // (30) 0) key
+ case GDK_1:
+ return VK_1; // (31) 1 ! key
+ case GDK_2:
+ case GDK_at:
+ return VK_2; // (32) 2 & key
+ case GDK_3:
+ case GDK_numbersign:
+ return VK_3; //case '3': case '#';
+ case GDK_4:
+ case GDK_dollar: // (34) 4 key '$';
+ return VK_4;
+ case GDK_5:
+ case GDK_percent:
+ return VK_5; // (35) 5 key '%'
+ case GDK_6:
+ case GDK_asciicircum:
+ return VK_6; // (36) 6 key '^'
+ case GDK_7:
+ case GDK_ampersand:
+ return VK_7; // (37) 7 key case '&'
+ case GDK_8:
+ case GDK_asterisk:
+ return VK_8; // (38) 8 key '*'
+ case GDK_9:
+ case GDK_parenright:
+ return VK_9; // (39) 9 key '('
+ case GDK_a:
+ case GDK_A:
+ return VK_A; // (41) A key case 'a': case 'A': return 0x41;
+ case GDK_b:
+ case GDK_B:
+ return VK_B; // (42) B key case 'b': case 'B': return 0x42;
+ case GDK_c:
+ case GDK_C:
+ return VK_C; // (43) C key case 'c': case 'C': return 0x43;
+ case GDK_d:
+ case GDK_D:
+ return VK_D; // (44) D key case 'd': case 'D': return 0x44;
+ case GDK_e:
+ case GDK_E:
+ return VK_E; // (45) E key case 'e': case 'E': return 0x45;
+ case GDK_f:
+ case GDK_F:
+ return VK_F; // (46) F key case 'f': case 'F': return 0x46;
+ case GDK_g:
+ case GDK_G:
+ return VK_G; // (47) G key case 'g': case 'G': return 0x47;
+ case GDK_h:
+ case GDK_H:
+ return VK_H; // (48) H key case 'h': case 'H': return 0x48;
+ case GDK_i:
+ case GDK_I:
+ return VK_I; // (49) I key case 'i': case 'I': return 0x49;
+ case GDK_j:
+ case GDK_J:
+ return VK_J; // (4A) J key case 'j': case 'J': return 0x4A;
+ case GDK_k:
+ case GDK_K:
+ return VK_K; // (4B) K key case 'k': case 'K': return 0x4B;
+ case GDK_l:
+ case GDK_L:
+ return VK_L; // (4C) L key case 'l': case 'L': return 0x4C;
+ case GDK_m:
+ case GDK_M:
+ return VK_M; // (4D) M key case 'm': case 'M': return 0x4D;
+ case GDK_n:
+ case GDK_N:
+ return VK_N; // (4E) N key case 'n': case 'N': return 0x4E;
+ case GDK_o:
+ case GDK_O:
+ return VK_O; // (4F) O key case 'o': case 'O': return 0x4F;
+ case GDK_p:
+ case GDK_P:
+ return VK_P; // (50) P key case 'p': case 'P': return 0x50;
+ case GDK_q:
+ case GDK_Q:
+ return VK_Q; // (51) Q key case 'q': case 'Q': return 0x51;
+ case GDK_r:
+ case GDK_R:
+ return VK_R; // (52) R key case 'r': case 'R': return 0x52;
+ case GDK_s:
+ case GDK_S:
+ return VK_S; // (53) S key case 's': case 'S': return 0x53;
+ case GDK_t:
+ case GDK_T:
+ return VK_T; // (54) T key case 't': case 'T': return 0x54;
+ case GDK_u:
+ case GDK_U:
+ return VK_U; // (55) U key case 'u': case 'U': return 0x55;
+ case GDK_v:
+ case GDK_V:
+ return VK_V; // (56) V key case 'v': case 'V': return 0x56;
+ case GDK_w:
+ case GDK_W:
+ return VK_W; // (57) W key case 'w': case 'W': return 0x57;
+ case GDK_x:
+ case GDK_X:
+ return VK_X; // (58) X key case 'x': case 'X': return 0x58;
+ case GDK_y:
+ case GDK_Y:
+ return VK_Y; // (59) Y key case 'y': case 'Y': return 0x59;
+ case GDK_z:
+ case GDK_Z:
+ return VK_Z; // (5A) Z key case 'z': case 'Z': return 0x5A;
+ case GDK_Meta_L:
+ return VK_LWIN; // (5B) Left Windows key (Microsoft Natural keyboard)
+ case GDK_Meta_R:
+ return VK_RWIN; // (5C) Right Windows key (Natural keyboard)
+ // VK_APPS (5D) Applications key (Natural keyboard)
+ // VK_SLEEP (5F) Computer Sleep key
+ // VK_SEPARATOR (6C) Separator key
+ // VK_SUBTRACT (6D) Subtract key
+ // VK_DECIMAL (6E) Decimal key
+ // VK_DIVIDE (6F) Divide key
+ // handled by key code above
+
+ case GDK_Num_Lock:
+ return VK_NUMLOCK; // (90) NUM LOCK key
+
+ case GDK_Scroll_Lock:
+ return VK_SCROLL; // (91) SCROLL LOCK key
+
+ // VK_LSHIFT (A0) Left SHIFT key
+ // VK_RSHIFT (A1) Right SHIFT key
+ // VK_LCONTROL (A2) Left CONTROL key
+ // VK_RCONTROL (A3) Right CONTROL key
+ // VK_LMENU (A4) Left MENU key
+ // VK_RMENU (A5) Right MENU key
+ // VK_BROWSER_BACK (A6) Windows 2000/XP: Browser Back key
+ // VK_BROWSER_FORWARD (A7) Windows 2000/XP: Browser Forward key
+ // VK_BROWSER_REFRESH (A8) Windows 2000/XP: Browser Refresh key
+ // VK_BROWSER_STOP (A9) Windows 2000/XP: Browser Stop key
+ // VK_BROWSER_SEARCH (AA) Windows 2000/XP: Browser Search key
+ // VK_BROWSER_FAVORITES (AB) Windows 2000/XP: Browser Favorites key
+ // VK_BROWSER_HOME (AC) Windows 2000/XP: Browser Start and Home key
+ // VK_VOLUME_MUTE (AD) Windows 2000/XP: Volume Mute key
+ // VK_VOLUME_DOWN (AE) Windows 2000/XP: Volume Down key
+ // VK_VOLUME_UP (AF) Windows 2000/XP: Volume Up key
+ // VK_MEDIA_NEXT_TRACK (B0) Windows 2000/XP: Next Track key
+ // VK_MEDIA_PREV_TRACK (B1) Windows 2000/XP: Previous Track key
+ // VK_MEDIA_STOP (B2) Windows 2000/XP: Stop Media key
+ // VK_MEDIA_PLAY_PAUSE (B3) Windows 2000/XP: Play/Pause Media key
+ // VK_LAUNCH_MAIL (B4) Windows 2000/XP: Start Mail key
+ // VK_LAUNCH_MEDIA_SELECT (B5) Windows 2000/XP: Select Media key
+ // VK_LAUNCH_APP1 (B6) Windows 2000/XP: Start Application 1 key
+ // VK_LAUNCH_APP2 (B7) Windows 2000/XP: Start Application 2 key
+
+ // VK_OEM_1 (BA) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ';:' key
+ case GDK_semicolon:
+ case GDK_colon:
+ return VK_OEM_1; //case ';': case ':': return 0xBA;
+ // VK_OEM_PLUS (BB) Windows 2000/XP: For any country/region, the '+' key
+ case GDK_plus:
+ case GDK_equal:
+ return VK_OEM_PLUS; //case '=': case '+': return 0xBB;
+ // VK_OEM_COMMA (BC) Windows 2000/XP: For any country/region, the ',' key
+ case GDK_comma:
+ case GDK_less:
+ return VK_OEM_COMMA; //case ',': case '<': return 0xBC;
+ // VK_OEM_MINUS (BD) Windows 2000/XP: For any country/region, the '-' key
+ case GDK_minus:
+ case GDK_underscore:
+ return VK_OEM_MINUS; //case '-': case '_': return 0xBD;
+ // VK_OEM_PERIOD (BE) Windows 2000/XP: For any country/region, the '.' key
+ case GDK_period:
+ case GDK_greater:
+ return VK_OEM_PERIOD; //case '.': case '>': return 0xBE;
+ // VK_OEM_2 (BF) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '/?' key
+ case GDK_slash:
+ case GDK_question:
+ return VK_OEM_2; //case '/': case '?': return 0xBF;
+ // VK_OEM_3 (C0) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '`~' key
+ case GDK_asciitilde:
+ case GDK_quoteleft:
+ return VK_OEM_3; //case '`': case '~': return 0xC0;
+ // VK_OEM_4 (DB) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '[{' key
+ case GDK_bracketleft:
+ case GDK_braceleft:
+ return VK_OEM_4; //case '[': case '{': return 0xDB;
+ // VK_OEM_5 (DC) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '\|' key
+ case GDK_backslash:
+ case GDK_bar:
+ return VK_OEM_5; //case '\\': case '|': return 0xDC;
+ // VK_OEM_6 (DD) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ']}' key
+ case GDK_bracketright:
+ case GDK_braceright:
+ return VK_OEM_6; // case ']': case '}': return 0xDD;
+ // VK_OEM_7 (DE) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key
+ case GDK_quoteright:
+ case GDK_quotedbl:
+ return VK_OEM_7; // case '\'': case '"': return 0xDE;
+ // VK_OEM_8 (DF) Used for miscellaneous characters; it can vary by keyboard.
+ // VK_OEM_102 (E2) Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard
+ // VK_PROCESSKEY (E5) Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key
+ // VK_PACKET (E7) Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT,SendInput, WM_KEYDOWN, and WM_KEYUP
+ // VK_ATTN (F6) Attn key
+ // VK_CRSEL (F7) CrSel key
+ // VK_EXSEL (F8) ExSel key
+ // VK_EREOF (F9) Erase EOF key
+ // VK_PLAY (FA) Play key
+ // VK_ZOOM (FB) Zoom key
+ // VK_NONAME (FC) Reserved for future use
+ // VK_PA1 (FD) PA1 key
+ // VK_OEM_CLEAR (FE) Clear key
+ default:
+ return 0;
+ }
+
+}
+
+static String singleCharacterString(guint val)
+{
+ switch (val) {
+ case GDK_ISO_Enter:
+ case GDK_KP_Enter:
+ case GDK_Return:
+ return String("\r");
+ default:
+ gunichar c = gdk_keyval_to_unicode(val);
+ glong nwc;
+ gunichar2* uchar16 = g_ucs4_to_utf16(&c, 1, 0, &nwc, 0);
+
+ String retVal;
+ if (uchar16)
+ retVal = String((UChar*)uchar16, nwc);
+ else
+ retVal = String();
+
+ g_free(uchar16);
+
+ return retVal;
+ }
+}
+
+// Keep this in sync with the other platform event constructors
+// TODO: m_gdkEventKey should be refcounted
+PlatformKeyboardEvent::PlatformKeyboardEvent(GdkEventKey* event)
+ : m_type((event->type == GDK_KEY_RELEASE) ? KeyUp : KeyDown)
+ , m_text(singleCharacterString(event->keyval))
+ , m_unmodifiedText(singleCharacterString(event->keyval))
+ , m_keyIdentifier(keyIdentifierForGdkKeyCode(event->keyval))
+ , m_autoRepeat(false)
+ , m_windowsVirtualKeyCode(windowsKeyCodeForKeyEvent(event->keyval))
+ , m_nativeVirtualKeyCode(event->keyval)
+ , m_isKeypad(event->keyval >= GDK_KP_Space && event->keyval <= GDK_KP_9)
+ , m_shiftKey((event->state & GDK_SHIFT_MASK) || (event->keyval == GDK_3270_BackTab))
+ , m_ctrlKey(event->state & GDK_CONTROL_MASK)
+ , m_altKey(event->state & GDK_MOD1_MASK)
+#if GTK_CHECK_VERSION(2,10,0)
+ , m_metaKey(event->state & GDK_META_MASK)
+#else
+ // GDK_MOD2_MASK doesn't always mean meta so we can't use it
+ , m_metaKey(false)
+#endif
+ , m_gdkEventKey(event)
+{
+}
+
+void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool backwardCompatibilityMode)
+{
+ // Can only change type from KeyDown to RawKeyDown or Char, as we lack information for other conversions.
+ ASSERT(m_type == KeyDown);
+ m_type = type;
+
+ if (backwardCompatibilityMode)
+ return;
+
+ if (type == RawKeyDown) {
+ m_text = String();
+ m_unmodifiedText = String();
+ } else {
+ m_keyIdentifier = String();
+ m_windowsVirtualKeyCode = 0;
+ }
+}
+
+bool PlatformKeyboardEvent::currentCapsLockState()
+{
+ notImplemented();
+ return false;
+}
+
+GdkEventKey* PlatformKeyboardEvent::gdkEventKey() const
+{
+ return m_gdkEventKey;
+}
+
+}
diff --git a/WebCore/platform/gtk/KeyboardCodes.h b/WebCore/platform/gtk/KeyboardCodes.h
new file mode 100644
index 0000000..3ad1243
--- /dev/null
+++ b/WebCore/platform/gtk/KeyboardCodes.h
@@ -0,0 +1,543 @@
+/*
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef KeyboardCodes_h
+#define KeyboardCodes_h
+
+namespace WebCore {
+
+// VK_LBUTTON (01) Left mouse button
+// VK_RBUTTON (02) Right mouse button
+// VK_CANCEL (03) Control-break processing
+// VK_MBUTTON (04) Middle mouse button (three-button mouse)
+// VK_XBUTTON1 (05)
+// VK_XBUTTON2 (06)
+
+// VK_BACK (08) BACKSPACE key
+const int VK_BACK = 0x08;
+
+// VK_TAB (09) TAB key
+const int VK_TAB = 0x09;
+
+// VK_CLEAR (0C) CLEAR key
+const int VK_CLEAR = 0x0C;
+
+// VK_RETURN (0D)
+const int VK_RETURN = 0x0D;
+
+// VK_SHIFT (10) SHIFT key
+const int VK_SHIFT = 0x10;
+
+// VK_CONTROL (11) CTRL key
+const int VK_CONTROL = 0x11;
+
+// VK_MENU (12) ALT key
+const int VK_MENU = 0x12;
+
+// VK_PAUSE (13) PAUSE key
+const int VK_PAUSE = 0x13;
+
+// VK_CAPITAL (14) CAPS LOCK key
+const int VK_CAPITAL = 0x14;
+
+// VK_KANA (15) Input Method Editor (IME) Kana mode
+const int VK_KANA = 0x15;
+
+// VK_HANGUEL (15) IME Hanguel mode (maintained for compatibility; use VK_HANGUL)
+// VK_HANGUL (15) IME Hangul mode
+const int VK_HANGUL = 0x15;
+
+// VK_JUNJA (17) IME Junja mode
+const int VK_JUNJA = 0x17;
+
+// VK_FINAL (18) IME final mode
+const int VK_FINAL = 0x18;
+
+// VK_HANJA (19) IME Hanja mode
+const int VK_HANJA = 0x19;
+
+// VK_KANJI (19) IME Kanji mode
+const int VK_KANJI = 0x19;
+
+// VK_ESCAPE (1B) ESC key
+const int VK_ESCAPE = 0x1B;
+
+// VK_CONVERT (1C) IME convert
+const int VK_CONVERT = 0x1C;
+
+// VK_NONCONVERT (1D) IME nonconvert
+const int VK_NONCONVERT = 0x1D;
+
+// VK_ACCEPT (1E) IME accept
+const int VK_ACCEPT = 0x1E;
+
+// VK_MODECHANGE (1F) IME mode change request
+const int VK_MODECHANGE = 0x1F;
+
+// VK_SPACE (20) SPACEBAR
+const int VK_SPACE = 0x20;
+
+// VK_PRIOR (21) PAGE UP key
+const int VK_PRIOR = 0x21;
+
+// VK_NEXT (22) PAGE DOWN key
+const int VK_NEXT = 0x22;
+
+// VK_END (23) END key
+const int VK_END = 0x23;
+
+// VK_HOME (24) HOME key
+const int VK_HOME = 0x24;
+
+// VK_LEFT (25) LEFT ARROW key
+const int VK_LEFT = 0x25;
+
+// VK_UP (26) UP ARROW key
+const int VK_UP = 0x26;
+
+// VK_RIGHT (27) RIGHT ARROW key
+const int VK_RIGHT = 0x27;
+
+// VK_DOWN (28) DOWN ARROW key
+const int VK_DOWN = 0x28;
+
+// VK_SELECT (29) SELECT key
+const int VK_SELECT = 0x29;
+
+// VK_PRINT (2A) PRINT key
+const int VK_PRINT = 0x2A;
+
+// VK_EXECUTE (2B) EXECUTE key
+const int VK_EXECUTE = 0x2B;
+
+// VK_SNAPSHOT (2C) PRINT SCREEN key
+const int VK_SNAPSHOT = 0x2C;
+
+// VK_INSERT (2D) INS key
+const int VK_INSERT = 0x2D;
+
+// VK_DELETE (2E) DEL key
+const int VK_DELETE = 0x2E;
+
+// VK_HELP (2F) HELP key
+const int VK_HELP = 0x2F;
+
+// (30) 0 key
+const int VK_0 = 0x30;
+
+// (31) 1 key
+const int VK_1 = 0x31;
+
+// (32) 2 key
+const int VK_2 = 0x32;
+
+// (33) 3 key
+const int VK_3 = 0x33;
+
+// (34) 4 key
+const int VK_4 = 0x34;
+
+// (35) 5 key;
+
+const int VK_5 = 0x35;
+
+// (36) 6 key
+const int VK_6 = 0x36;
+
+// (37) 7 key
+const int VK_7 = 0x37;
+
+// (38) 8 key
+const int VK_8 = 0x38;
+
+// (39) 9 key
+const int VK_9 = 0x39;
+
+// (41) A key
+const int VK_A = 0x41;
+
+// (42) B key
+const int VK_B = 0x42;
+
+// (43) C key
+const int VK_C = 0x43;
+
+// (44) D key
+const int VK_D = 0x44;
+
+// (45) E key
+const int VK_E = 0x45;
+
+// (46) F key
+const int VK_F = 0x46;
+
+// (47) G key
+const int VK_G = 0x47;
+
+// (48) H key
+const int VK_H = 0x48;
+
+// (49) I key
+const int VK_I = 0x49;
+
+// (4A) J key
+const int VK_J = 0x4A;
+
+// (4B) K key
+const int VK_K = 0x4B;
+
+// (4C) L key
+const int VK_L = 0x4C;
+
+// (4D) M key
+const int VK_M = 0x4D;
+
+// (4E) N key
+const int VK_N = 0x4E;
+
+// (4F) O key
+const int VK_O = 0x4F;
+
+// (50) P key
+const int VK_P = 0x50;
+
+// (51) Q key
+const int VK_Q = 0x51;
+
+// (52) R key
+const int VK_R = 0x52;
+
+// (53) S key
+const int VK_S = 0x53;
+
+// (54) T key
+const int VK_T = 0x54;
+
+// (55) U key
+const int VK_U = 0x55;
+
+// (56) V key
+const int VK_V = 0x56;
+
+// (57) W key
+const int VK_W = 0x57;
+
+// (58) X key
+const int VK_X = 0x58;
+
+// (59) Y key
+const int VK_Y = 0x59;
+
+// (5A) Z key
+const int VK_Z = 0x5A;
+
+// VK_LWIN (5B) Left Windows key (Microsoft Natural keyboard)
+const int VK_LWIN = 0x5B;
+
+// VK_RWIN (5C) Right Windows key (Natural keyboard)
+const int VK_RWIN = 0x5C;
+
+// VK_APPS (5D) Applications key (Natural keyboard)
+const int VK_APPS = 0x5D;
+
+// VK_SLEEP (5F) Computer Sleep key
+const int VK_SLEEP = 0x5F;
+
+// VK_NUMPAD0 (60) Numeric keypad 0 key
+const int VK_NUMPAD0 = 0x60;
+
+// VK_NUMPAD1 (61) Numeric keypad 1 key
+const int VK_NUMPAD1 = 0x61;
+
+// VK_NUMPAD2 (62) Numeric keypad 2 key
+const int VK_NUMPAD2 = 0x62;
+
+// VK_NUMPAD3 (63) Numeric keypad 3 key
+const int VK_NUMPAD3 = 0x63;
+
+// VK_NUMPAD4 (64) Numeric keypad 4 key
+const int VK_NUMPAD4 = 0x64;
+
+// VK_NUMPAD5 (65) Numeric keypad 5 key
+const int VK_NUMPAD5 = 0x65;
+
+// VK_NUMPAD6 (66) Numeric keypad 6 key
+const int VK_NUMPAD6 = 0x66;
+
+// VK_NUMPAD7 (67) Numeric keypad 7 key
+const int VK_NUMPAD7 = 0x67;
+
+// VK_NUMPAD8 (68) Numeric keypad 8 key
+const int VK_NUMPAD8 = 0x68;
+
+// VK_NUMPAD9 (69) Numeric keypad 9 key
+const int VK_NUMPAD9 = 0x69;
+
+// VK_MULTIPLY (6A) Multiply key
+const int VK_MULTIPLY = 0x6A;
+
+// VK_ADD (6B) Add key
+const int VK_ADD = 0x6B;
+
+// VK_SEPARATOR (6C) Separator key
+const int VK_SEPARATOR = 0x6C;
+
+// VK_SUBTRACT (6D) Subtract key
+const int VK_SUBTRACT = 0x6D;
+
+// VK_DECIMAL (6E) Decimal key
+const int VK_DECIMAL = 0x6E;
+
+// VK_DIVIDE (6F) Divide key
+const int VK_DIVIDE = 0x6F;
+
+// VK_F1 (70) F1 key
+const int VK_F1 = 0x70;
+
+// VK_F2 (71) F2 key
+const int VK_F2 = 0x71;
+
+// VK_F3 (72) F3 key
+const int VK_F3 = 0x72;
+
+// VK_F4 (73) F4 key
+const int VK_F4 = 0x73;
+
+// VK_F5 (74) F5 key
+const int VK_F5 = 0x74;
+
+// VK_F6 (75) F6 key
+const int VK_F6 = 0x75;
+
+// VK_F7 (76) F7 key
+const int VK_F7 = 0x76;
+
+// VK_F8 (77) F8 key
+const int VK_F8 = 0x77;
+
+// VK_F9 (78) F9 key
+const int VK_F9 = 0x78;
+
+// VK_F10 (79) F10 key
+const int VK_F10 = 0x79;
+
+// VK_F11 (7A) F11 key
+const int VK_F11 = 0x7A;
+
+// VK_F12 (7B) F12 key
+const int VK_F12 = 0x7B;
+
+// VK_F13 (7C) F13 key
+const int VK_F13 = 0x7C;
+
+// VK_F14 (7D) F14 key
+const int VK_F14 = 0x7D;
+
+// VK_F15 (7E) F15 key
+const int VK_F15 = 0x7E;
+
+// VK_F16 (7F) F16 key
+const int VK_F16 = 0x7F;
+
+// VK_F17 (80H) F17 key
+const int VK_F17 = 0x80;
+
+// VK_F18 (81H) F18 key
+const int VK_F18 = 0x81;
+
+// VK_F19 (82H) F19 key
+const int VK_F19 = 0x82;
+
+// VK_F20 (83H) F20 key
+const int VK_F20 = 0x83;
+
+// VK_F21 (84H) F21 key
+const int VK_F21 = 0x84;
+
+// VK_F22 (85H) F22 key
+const int VK_F22 = 0x85;
+
+// VK_F23 (86H) F23 key
+const int VK_F23 = 0x86;
+
+// VK_F24 (87H) F24 key
+const int VK_F24 = 0x87;
+
+// VK_NUMLOCK (90) NUM LOCK key
+const int VK_NUMLOCK = 0x90;
+
+// VK_SCROLL (91) SCROLL LOCK key
+const int VK_SCROLL = 0x91;
+
+// VK_LSHIFT (A0) Left SHIFT key
+const int VK_LSHIFT = 0xA0;
+
+// VK_RSHIFT (A1) Right SHIFT key
+const int VK_RSHIFT = 0xA1;
+
+// VK_LCONTROL (A2) Left CONTROL key
+const int VK_LCONTROL = 0xA2;
+
+// VK_RCONTROL (A3) Right CONTROL key
+const int VK_RCONTROL = 0xA3;
+
+// VK_LMENU (A4) Left MENU key
+const int VK_LMENU = 0xA4;
+
+// VK_RMENU (A5) Right MENU key
+const int VK_RMENU = 0xA5;
+
+// VK_BROWSER_BACK (A6) Windows 2000/XP: Browser Back key
+const int VK_BROWSER_BACK = 0xA6;
+
+// VK_BROWSER_FORWARD (A7) Windows 2000/XP: Browser Forward key
+const int VK_BROWSER_FORWARD = 0xA7;
+
+// VK_BROWSER_REFRESH (A8) Windows 2000/XP: Browser Refresh key
+const int VK_BROWSER_REFRESH = 0xA8;
+
+// VK_BROWSER_STOP (A9) Windows 2000/XP: Browser Stop key
+const int VK_BROWSER_STOP = 0xA9;
+
+// VK_BROWSER_SEARCH (AA) Windows 2000/XP: Browser Search key
+const int VK_BROWSER_SEARCH = 0xAA;
+
+// VK_BROWSER_FAVORITES (AB) Windows 2000/XP: Browser Favorites key
+const int VK_BROWSER_FAVORITES = 0xAB;
+
+// VK_BROWSER_HOME (AC) Windows 2000/XP: Browser Start and Home key
+const int VK_BROWSER_HOME = 0xAC;
+
+// VK_VOLUME_MUTE (AD) Windows 2000/XP: Volume Mute key
+const int VK_VOLUME_MUTE = 0xAD;
+
+// VK_VOLUME_DOWN (AE) Windows 2000/XP: Volume Down key
+const int VK_VOLUME_DOWN = 0xAE;
+
+// VK_VOLUME_UP (AF) Windows 2000/XP: Volume Up key
+const int VK_VOLUME_UP = 0xAF;
+
+// VK_MEDIA_NEXT_TRACK (B0) Windows 2000/XP: Next Track key
+const int VK_MEDIA_NEXT_TRACK = 0xB0;
+
+// VK_MEDIA_PREV_TRACK (B1) Windows 2000/XP: Previous Track key
+const int VK_MEDIA_PREV_TRACK = 0xB1;
+
+// VK_MEDIA_STOP (B2) Windows 2000/XP: Stop Media key
+const int VK_MEDIA_STOP = 0xB2;
+
+// VK_MEDIA_PLAY_PAUSE (B3) Windows 2000/XP: Play/Pause Media key
+const int VK_MEDIA_PLAY_PAUSE = 0xB3;
+
+// VK_LAUNCH_MAIL (B4) Windows 2000/XP: Start Mail key
+const int VK_MEDIA_LAUNCH_MAIL = 0xB4;
+
+// VK_LAUNCH_MEDIA_SELECT (B5) Windows 2000/XP: Select Media key
+const int VK_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5;
+
+// VK_LAUNCH_APP1 (B6) Windows 2000/XP: Start Application 1 key
+const int VK_MEDIA_LAUNCH_APP1 = 0xB6;
+
+// VK_LAUNCH_APP2 (B7) Windows 2000/XP: Start Application 2 key
+const int VK_MEDIA_LAUNCH_APP2 = 0xB7;
+
+// VK_OEM_1 (BA) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ';:' key
+const int VK_OEM_1 = 0xBA;
+
+// VK_OEM_PLUS (BB) Windows 2000/XP: For any country/region, the '+' key
+const int VK_OEM_PLUS = 0xBB;
+
+// VK_OEM_COMMA (BC) Windows 2000/XP: For any country/region, the ',' key
+const int VK_OEM_COMMA = 0xBC;
+
+// VK_OEM_MINUS (BD) Windows 2000/XP: For any country/region, the '-' key
+const int VK_OEM_MINUS = 0xBD;
+
+// VK_OEM_PERIOD (BE) Windows 2000/XP: For any country/region, the '.' key
+const int VK_OEM_PERIOD = 0xBE;
+
+// VK_OEM_2 (BF) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '/?' key
+const int VK_OEM_2 = 0xBF;
+
+// VK_OEM_3 (C0) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '`~' key
+const int VK_OEM_3 = 0xC0;
+
+// VK_OEM_4 (DB) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '[{' key
+const int VK_OEM_4 = 0xDB;
+
+// VK_OEM_5 (DC) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '\|' key
+const int VK_OEM_5 = 0xDC;
+
+// VK_OEM_6 (DD) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ']}' key
+const int VK_OEM_6 = 0xDD;
+
+// VK_OEM_7 (DE) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key
+const int VK_OEM_7 = 0xDE;
+
+// VK_OEM_8 (DF) Used for miscellaneous characters; it can vary by keyboard.
+const int VK_OEM_8 = 0xDF;
+
+// VK_OEM_102 (E2) Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard
+const int VK_OEM_102 = 0xE2;
+
+// VK_PROCESSKEY (E5) Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key
+const int VK_PROCESSKEY = 0xE5;
+
+// VK_PACKET (E7) Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT,SendInput, WM_KEYDOWN, and WM_KEYUP
+const int VK_PACKET = 0xE7;
+
+// VK_ATTN (F6) Attn key
+const int VK_ATTN = 0xF6;
+
+// VK_CRSEL (F7) CrSel key
+const int VK_CRSEL = 0xF7;
+
+// VK_EXSEL (F8) ExSel key
+const int VK_EXSEL = 0xF8;
+
+// VK_EREOF (F9) Erase EOF key
+const int VK_EREOF = 0xF9;
+
+// VK_PLAY (FA) Play key
+const int VK_PLAY = 0xFA;
+
+// VK_ZOOM (FB) Zoom key
+const int VK_ZOOM = 0xFB;
+
+// VK_NONAME (FC) Reserved for future use
+const int VK_NONAME = 0xFC;
+
+// VK_PA1 (FD) PA1 key
+const int VK_PA1 = 0xFD;
+
+// VK_OEM_CLEAR (FE) Clear key
+const int VK_OEM_CLEAR = 0xFE;
+
+const int VK_UNKNOWN = 0;
+
+}
+
+#endif
diff --git a/WebCore/platform/gtk/Language.cpp b/WebCore/platform/gtk/Language.cpp
new file mode 100644
index 0000000..6ae7305
--- /dev/null
+++ b/WebCore/platform/gtk/Language.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "Language.h"
+
+#include "CString.h"
+#include "PlatformString.h"
+
+#include <gtk/gtk.h>
+#include <pango/pango.h>
+
+#if !defined(PANGO_VERSION_CHECK)
+// PANGO_VERSION_CHECK() and pango_language_get_default() appeared in 1.5.2
+#include <locale.h>
+
+static gchar *
+_pango_get_lc_ctype (void)
+{
+ return g_strdup (setlocale (LC_CTYPE, NULL));
+}
+
+static PangoLanguage *
+pango_language_get_default (void)
+{
+ static PangoLanguage *result = NULL;
+ if (G_UNLIKELY (!result))
+ {
+ gchar *lang = _pango_get_lc_ctype ();
+ result = pango_language_from_string (lang);
+ g_free (lang);
+ }
+ return result;
+}
+#endif
+
+namespace WebCore {
+
+String defaultLanguage()
+{
+ return pango_language_to_string(gtk_get_default_language());
+}
+
+}
diff --git a/WebCore/platform/gtk/LocalizedStringsGtk.cpp b/WebCore/platform/gtk/LocalizedStringsGtk.cpp
new file mode 100644
index 0000000..52d4f5f
--- /dev/null
+++ b/WebCore/platform/gtk/LocalizedStringsGtk.cpp
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ * Copyright (C) 2008 Christian Dywan <christian@imendio.com>
+ * Copyright (C) 2008 Nuanti Ltd.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "LocalizedStrings.h"
+#include "NotImplemented.h"
+#include "PlatformString.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+namespace WebCore {
+
+static const char* gtkStockLabel(const char* stockID)
+{
+ GtkStockItem item;
+ if (!gtk_stock_lookup(stockID, &item))
+ return stockID;
+ return item.label;
+}
+
+String submitButtonDefaultLabel()
+{
+ return String::fromUTF8(_("Submit"));
+}
+
+String inputElementAltText()
+{
+ return String::fromUTF8(_("Submit"));
+}
+
+String resetButtonDefaultLabel()
+{
+ return String::fromUTF8(_("Reset"));
+}
+
+String searchableIndexIntroduction()
+{
+ return String::fromUTF8(_("_Searchable Index"));
+}
+
+String fileButtonChooseFileLabel()
+{
+ return String::fromUTF8(_("Choose File"));
+}
+
+String fileButtonNoFileSelectedLabel()
+{
+ return String::fromUTF8(_("(None)"));
+}
+
+String contextMenuItemTagOpenLinkInNewWindow()
+{
+ return String::fromUTF8(_("Open Link in New _Window"));
+}
+
+String contextMenuItemTagDownloadLinkToDisk()
+{
+ return String::fromUTF8(_("_Download Linked File"));
+}
+
+String contextMenuItemTagCopyLinkToClipboard()
+{
+ return String::fromUTF8(_("Copy Link Loc_ation"));
+}
+
+String contextMenuItemTagOpenImageInNewWindow()
+{
+ return String::fromUTF8(_("Open _Image in New Window"));
+}
+
+String contextMenuItemTagDownloadImageToDisk()
+{
+ return String::fromUTF8(_("Sa_ve Image As"));
+}
+
+String contextMenuItemTagCopyImageToClipboard()
+{
+ return String::fromUTF8(_("Cop_y Image"));
+}
+
+String contextMenuItemTagOpenFrameInNewWindow()
+{
+ return String::fromUTF8(_("Open _Frame in New Window"));
+}
+
+String contextMenuItemTagCopy()
+{
+ static String stockLabel = String::fromUTF8(gtkStockLabel(GTK_STOCK_COPY));
+ return stockLabel;
+}
+
+String contextMenuItemTagDelete()
+{
+ static String stockLabel = String::fromUTF8(gtkStockLabel(GTK_STOCK_DELETE));
+ return stockLabel;
+}
+
+String contextMenuItemTagSelectAll()
+{
+#if GTK_CHECK_VERSION(2,10,0)
+ static String stockLabel = String::fromUTF8(gtkStockLabel(GTK_STOCK_SELECT_ALL));
+#else
+ static String stockLabel = String::fromUTF8(_("Select _All"));
+#endif
+ return stockLabel;
+}
+
+String contextMenuItemTagUnicode()
+{
+ return String::fromUTF8(_("_Insert Unicode Control Character"));
+}
+
+String contextMenuItemTagInputMethods()
+{
+ return String::fromUTF8(_("Input _Methods"));
+}
+
+String contextMenuItemTagGoBack()
+{
+ static String stockLabel = String::fromUTF8(gtkStockLabel(GTK_STOCK_GO_BACK));
+ return stockLabel;
+}
+
+String contextMenuItemTagGoForward()
+{
+ static String stockLabel = String::fromUTF8(gtkStockLabel(GTK_STOCK_GO_FORWARD));
+ return stockLabel;
+}
+
+String contextMenuItemTagStop()
+{
+ static String stockLabel = String::fromUTF8(gtkStockLabel(GTK_STOCK_STOP));
+ return stockLabel;
+}
+
+String contextMenuItemTagReload()
+{
+ return String::fromUTF8(_("_Reload"));
+}
+
+String contextMenuItemTagCut()
+{
+ static String stockLabel = String::fromUTF8(gtkStockLabel(GTK_STOCK_CUT));
+ return stockLabel;
+}
+
+String contextMenuItemTagPaste()
+{
+ static String stockLabel = String::fromUTF8(gtkStockLabel(GTK_STOCK_PASTE));
+ return stockLabel;
+}
+
+String contextMenuItemTagNoGuessesFound()
+{
+ return String::fromUTF8(_("No Guesses Found"));
+}
+
+String contextMenuItemTagIgnoreSpelling()
+{
+ return String::fromUTF8(_("_Ignore Spelling"));
+}
+
+String contextMenuItemTagLearnSpelling()
+{
+ return String::fromUTF8(_("_Learn Spelling"));
+}
+
+String contextMenuItemTagSearchWeb()
+{
+ return String::fromUTF8(_("_Search the Web"));
+}
+
+String contextMenuItemTagLookUpInDictionary()
+{
+ return String::fromUTF8(_("_Look Up in Dictionary"));
+}
+
+String contextMenuItemTagOpenLink()
+{
+ return String::fromUTF8(_("_Open Link"));
+}
+
+String contextMenuItemTagIgnoreGrammar()
+{
+ return String::fromUTF8(_("Ignore _Grammar"));
+}
+
+String contextMenuItemTagSpellingMenu()
+{
+ return String::fromUTF8(_("Spelling and _Grammar"));
+}
+
+String contextMenuItemTagShowSpellingPanel(bool show)
+{
+ return String::fromUTF8(show ? _("_Show Spelling and Grammar") : _("_Hide Spelling and Grammar"));
+}
+
+String contextMenuItemTagCheckSpelling()
+{
+ return String::fromUTF8(_("_Check Document Now"));
+}
+
+String contextMenuItemTagCheckSpellingWhileTyping()
+{
+ return String::fromUTF8(_("Check Spelling While _Typing"));
+}
+
+String contextMenuItemTagCheckGrammarWithSpelling()
+{
+ return String::fromUTF8(_("Check _Grammar With Spelling"));
+}
+
+String contextMenuItemTagFontMenu()
+{
+ return String::fromUTF8(_("_Font"));
+}
+
+String contextMenuItemTagBold()
+{
+ static String stockLabel = String::fromUTF8(gtkStockLabel(GTK_STOCK_BOLD));
+ return stockLabel;
+}
+
+String contextMenuItemTagItalic()
+{
+ static String stockLabel = String::fromUTF8(gtkStockLabel(GTK_STOCK_ITALIC));
+ return stockLabel;
+}
+
+String contextMenuItemTagUnderline()
+{
+ static String stockLabel = String::fromUTF8(gtkStockLabel(GTK_STOCK_UNDERLINE));
+ return stockLabel;
+}
+
+String contextMenuItemTagOutline()
+{
+ return String::fromUTF8(_("_Outline"));
+}
+
+String contextMenuItemTagInspectElement()
+{
+ return String::fromUTF8(_("Inspect _Element"));
+}
+
+String searchMenuNoRecentSearchesText()
+{
+ return String::fromUTF8(_("No recent searches"));
+}
+
+String searchMenuRecentSearchesText()
+{
+ return String::fromUTF8(_("Recent searches"));
+}
+
+String searchMenuClearRecentSearchesText()
+{
+ return String::fromUTF8(_("_Clear recent searches"));
+}
+
+String AXDefinitionListTermText()
+{
+ return String::fromUTF8(_("term"));
+}
+
+String AXDefinitionListDefinitionText()
+{
+ return String::fromUTF8(_("definition"));
+}
+
+String AXButtonActionVerb()
+{
+ return String::fromUTF8(_("press"));
+}
+
+String AXRadioButtonActionVerb()
+{
+ return String::fromUTF8(_("select"));
+}
+
+String AXTextFieldActionVerb()
+{
+ return String::fromUTF8(_("activate"));
+}
+
+String AXCheckedCheckBoxActionVerb()
+{
+ return String::fromUTF8(_("uncheck"));
+}
+
+String AXUncheckedCheckBoxActionVerb()
+{
+ return String::fromUTF8(_("check"));
+}
+
+String AXLinkActionVerb()
+{
+ return String::fromUTF8(_("jump"));
+}
+
+String multipleFileUploadText(unsigned numberOfFiles)
+{
+ // FIXME: If this file gets localized, this should really be localized as one string with a wildcard for the number.
+ return String::number(numberOfFiles) + String::fromUTF8(_(" files"));
+}
+
+String unknownFileSizeText()
+{
+ return String::fromUTF8(_("Unknown"));
+}
+
+String imageTitle(const String& filename, const IntSize& size)
+{
+ notImplemented();
+ return String();
+}
+
+}
diff --git a/WebCore/platform/gtk/LoggingGtk.cpp b/WebCore/platform/gtk/LoggingGtk.cpp
new file mode 100644
index 0000000..5bc1559
--- /dev/null
+++ b/WebCore/platform/gtk/LoggingGtk.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "Logging.h"
+
+namespace WebCore {
+
+void InitializeLoggingChannelsIfNecessary()
+{
+ // FIXME: Add a way for the user to specify which
+ // logs he/she would like turned on.
+ LogNotYetImplemented.state = WTFLogChannelOn;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/gtk/MIMETypeRegistryGtk.cpp b/WebCore/platform/gtk/MIMETypeRegistryGtk.cpp
new file mode 100644
index 0000000..20fe0cb
--- /dev/null
+++ b/WebCore/platform/gtk/MIMETypeRegistryGtk.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MIMETypeRegistry.h"
+
+namespace WebCore {
+
+struct ExtensionMap {
+ const char* extension;
+ const char* mimeType;
+};
+
+static const ExtensionMap extensionMap [] = {
+ { "bmp", "image/bmp" },
+ { "css", "text/css" },
+ { "gif", "image/gif" },
+ { "html", "text/html" },
+ { "ico", "image/x-icon" },
+ { "jpeg", "image/jpeg" },
+ { "jpg", "image/jpeg" },
+ { "js", "application/x-javascript" },
+ { "pdf", "application/pdf" },
+ { "png", "image/png" },
+ { "rss", "application/rss+xml" },
+ { "svg", "image/svg+xml" },
+ { "text", "text/plain" },
+ { "txt", "text/plain" },
+ { "xbm", "image/x-xbitmap" },
+ { "xml", "text/xml" },
+ { "xsl", "text/xsl" },
+ { "xhtml", "application/xhtml+xml" },
+ { 0, 0 }
+};
+
+String MIMETypeRegistry::getMIMETypeForExtension(const String &ext)
+{
+ String s = ext.lower();
+ const ExtensionMap *e = extensionMap;
+ while (e->extension) {
+ if (s == e->extension)
+ return e->mimeType;
+ ++e;
+ }
+
+ return String();
+}
+
+}
diff --git a/WebCore/platform/gtk/MouseEventGtk.cpp b/WebCore/platform/gtk/MouseEventGtk.cpp
new file mode 100644
index 0000000..f441f00
--- /dev/null
+++ b/WebCore/platform/gtk/MouseEventGtk.cpp
@@ -0,0 +1,112 @@
+/*
+* Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "config.h"
+#include "PlatformMouseEvent.h"
+
+#include "SystemTime.h"
+#include "Assertions.h"
+
+#include <gdk/gdk.h>
+#include <gtk/gtkversion.h>
+
+namespace WebCore {
+
+// FIXME: Would be even better to figure out which modifier is Alt instead of always using GDK_MOD1_MASK.
+
+// Keep this in sync with the other platform event constructors
+PlatformMouseEvent::PlatformMouseEvent(GdkEventButton* event)
+{
+ m_timestamp = event->time;
+ m_position = IntPoint((int)event->x, (int)event->y);
+ m_globalPosition = IntPoint((int)event->x_root, (int)event->y_root);
+ m_shiftKey = event->state & GDK_SHIFT_MASK;
+ m_ctrlKey = event->state & GDK_CONTROL_MASK;
+ m_altKey = event->state & GDK_MOD1_MASK;
+#if GTK_CHECK_VERSION(2,10,0)
+ m_metaKey = event->state & GDK_META_MASK;
+#else
+ // GDK_MOD2_MASK doesn't always mean meta so we can't use it
+ m_metaKey = false;
+#endif
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ m_eventType = MouseEventPressed;
+ if (event->type == GDK_BUTTON_RELEASE) {
+ m_eventType = MouseEventReleased;
+ m_clickCount = 0;
+ } else if (event->type == GDK_BUTTON_PRESS)
+ m_clickCount = 1;
+ else if (event->type == GDK_2BUTTON_PRESS)
+ m_clickCount = 2;
+ else if (event->type == GDK_3BUTTON_PRESS)
+ m_clickCount = 3;
+
+ if (event->button == 1)
+ m_button = LeftButton;
+ else if (event->button == 2)
+ m_button = MiddleButton;
+ else if (event->button == 3)
+ m_button = RightButton;
+ break;
+
+ default:
+ ASSERT_NOT_REACHED();
+ };
+}
+
+PlatformMouseEvent::PlatformMouseEvent(GdkEventMotion* motion)
+{
+ m_timestamp = motion->time;
+ m_position = IntPoint((int)motion->x, (int)motion->y);
+ m_globalPosition = IntPoint((int)motion->x_root, (int)motion->y_root);
+ m_shiftKey = motion->state & GDK_SHIFT_MASK;
+ m_ctrlKey = motion->state & GDK_CONTROL_MASK;
+ m_altKey = motion->state & GDK_MOD1_MASK;
+ m_metaKey = motion->state & GDK_MOD2_MASK;
+
+ switch (motion->type) {
+ case GDK_MOTION_NOTIFY:
+ m_eventType = MouseEventMoved;
+ m_button = NoButton;
+ m_clickCount = 0;
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ };
+
+ if (motion->state & GDK_BUTTON1_MASK)
+ m_button = LeftButton;
+ else if (motion->state & GDK_BUTTON2_MASK)
+ m_button = MiddleButton;
+ else if (motion->state & GDK_BUTTON3_MASK)
+ m_button = RightButton;
+}
+}
diff --git a/WebCore/platform/gtk/PasteboardGtk.cpp b/WebCore/platform/gtk/PasteboardGtk.cpp
new file mode 100644
index 0000000..15a7e64
--- /dev/null
+++ b/WebCore/platform/gtk/PasteboardGtk.cpp
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "Pasteboard.h"
+
+#include "CString.h"
+#include "DocumentFragment.h"
+#include "Frame.h"
+#include "NotImplemented.h"
+#include "PlatformString.h"
+#include "Image.h"
+#include "RenderImage.h"
+#include "KURL.h"
+#include "markup.h"
+
+#include <gtk/gtk.h>
+
+namespace WebCore {
+
+/* FIXME: we must get rid of this and use the enum in webkitwebview.h someway */
+typedef enum
+{
+ WEBKIT_WEB_VIEW_TARGET_INFO_HTML = - 1,
+ WEBKIT_WEB_VIEW_TARGET_INFO_TEXT = - 2
+} WebKitWebViewTargetInfo;
+
+class PasteboardSelectionData {
+public:
+ PasteboardSelectionData(gchar* text, gchar* markup)
+ : m_text(text)
+ , m_markup(markup) { }
+
+ ~PasteboardSelectionData() {
+ g_free(m_text);
+ g_free(m_markup);
+ }
+
+ const gchar* text() const { return m_text; }
+ const gchar* markup() const { return m_markup; }
+
+private:
+ gchar* m_text;
+ gchar* m_markup;
+};
+
+static void clipboard_get_contents_cb(GtkClipboard *clipboard, GtkSelectionData *selection_data,
+ guint info, gpointer data) {
+ PasteboardSelectionData* clipboardData = reinterpret_cast<PasteboardSelectionData*>(data);
+ ASSERT(clipboardData);
+ if ((gint)info == WEBKIT_WEB_VIEW_TARGET_INFO_HTML) {
+ gtk_selection_data_set(selection_data, selection_data->target, 8,
+ reinterpret_cast<const guchar*>(clipboardData->markup()),
+ g_utf8_strlen(clipboardData->markup(), -1));
+ } else
+ gtk_selection_data_set_text(selection_data, clipboardData->text(), -1);
+}
+
+static void clipboard_clear_contents_cb(GtkClipboard *clipboard, gpointer data) {
+ PasteboardSelectionData* clipboardData = reinterpret_cast<PasteboardSelectionData*>(data);
+ ASSERT(clipboardData);
+ delete clipboardData;
+}
+
+
+Pasteboard* Pasteboard::generalPasteboard()
+{
+ static Pasteboard* pasteboard = new Pasteboard();
+ return pasteboard;
+}
+
+Pasteboard::Pasteboard()
+{
+ notImplemented();
+}
+
+Pasteboard::~Pasteboard()
+{
+ delete m_helper;
+}
+
+void Pasteboard::setHelper(PasteboardHelper* helper)
+{
+ m_helper = helper;
+}
+
+void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
+{
+ GtkClipboard* clipboard = m_helper->getClipboard(frame);
+#if GTK_CHECK_VERSION(2,10,0)
+ gchar* text = g_strdup(frame->selectedText().utf8().data());
+ gchar* markup = g_strdup(createMarkup(selectedRange, 0, AnnotateForInterchange).utf8().data());
+ PasteboardSelectionData* data = new PasteboardSelectionData(text, markup);
+
+ gint n_targets;
+ GtkTargetEntry* targets = gtk_target_table_new_from_list(m_helper->getCopyTargetList(frame), &n_targets);
+ gtk_clipboard_set_with_data(clipboard, targets, n_targets,
+ clipboard_get_contents_cb, clipboard_clear_contents_cb, data);
+ gtk_target_table_free(targets, n_targets);
+#else
+ gtk_clipboard_set_text(clipboard, frame->selectedText().utf8().data(), frame->selectedText().utf8().length());
+#endif
+}
+
+void Pasteboard::writeURL(const KURL& url, const String&, Frame* frame)
+{
+ if (url.isEmpty())
+ return;
+
+ GtkClipboard* clipboard = m_helper->getClipboard(frame);
+ gtk_clipboard_set_text(clipboard, url.string().utf8().data(), url.string().utf8().length());
+}
+
+void Pasteboard::writeImage(Node* node, const KURL&, const String&)
+{
+ // TODO: Enable this when Image gets GdkPixbuf support
+
+ /*
+ GtkClipboard* clipboard = gtk_clipboard_get_for_display(gdk_display_get_default(), GDK_SELECTION_CLIPBOARD);
+
+ ASSERT(node && node->renderer() && node->renderer()->isImage());
+ RenderImage* renderer = static_cast<RenderImage*>(node->renderer());
+ CachedImage* cachedImage = static_cast<CachedImage*>(renderer->cachedImage());
+ ASSERT(cachedImage);
+ Image* image = cachedImage->image();
+ ASSERT(image);
+
+ gtk_clipboard_set_image(clipboard, image->pixbuf());
+ */
+
+ notImplemented();
+}
+
+void Pasteboard::clear()
+{
+ GtkClipboard* clipboard = gtk_clipboard_get_for_display(gdk_display_get_default(), GDK_SELECTION_CLIPBOARD);
+
+ gtk_clipboard_clear(clipboard);
+}
+
+bool Pasteboard::canSmartReplace()
+{
+ notImplemented();
+ return false;
+}
+
+PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> context,
+ bool allowPlainText, bool& chosePlainText)
+{
+#if GTK_CHECK_VERSION(2,10,0)
+ GdkAtom textHtml = gdk_atom_intern_static_string("text/html");
+#else
+ GdkAtom textHtml = gdk_atom_intern("text/html", false);
+#endif
+ GtkClipboard* clipboard = m_helper->getClipboard(frame);
+ chosePlainText = false;
+
+ if (GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard, textHtml)) {
+ ASSERT(data->data);
+ String html = String::fromUTF8(reinterpret_cast<gchar*>(data->data), data->length * data->format / 8);
+ gtk_selection_data_free(data);
+
+ if (!html.isEmpty()) {
+ RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(frame->document(), html, "");
+ if (fragment)
+ return fragment.release();
+ }
+ }
+
+ if (!allowPlainText)
+ return 0;
+
+ if (gchar* utf8 = gtk_clipboard_wait_for_text(clipboard)) {
+ String text = String::fromUTF8(utf8);
+ g_free(utf8);
+
+ chosePlainText = true;
+ RefPtr<DocumentFragment> fragment = createFragmentFromText(context.get(), text);
+ if (fragment)
+ return fragment.release();
+ }
+
+ return 0;
+}
+
+String Pasteboard::plainText(Frame* frame)
+{
+ GtkClipboard* clipboard = m_helper->getClipboard(frame);
+
+ gchar* utf8 = gtk_clipboard_wait_for_text(clipboard);
+
+ if (!utf8)
+ return String();
+
+ String text = String::fromUTF8(utf8);
+ g_free(utf8);
+
+ return text;
+}
+
+}
diff --git a/WebCore/platform/gtk/PasteboardHelper.h b/WebCore/platform/gtk/PasteboardHelper.h
new file mode 100644
index 0000000..6bdc05e
--- /dev/null
+++ b/WebCore/platform/gtk/PasteboardHelper.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2007 Luca Bruno <lethalman88@gmail.com>
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PasteboardHelper_h
+#define PasteboardHelper_h
+
+/*
+ * FIXME: this is for WebCore support and must be removed once
+ * a better solution is found
+ */
+
+#include "Frame.h"
+
+#include <gtk/gtk.h>
+
+namespace WebCore {
+
+class PasteboardHelper {
+public:
+ virtual ~PasteboardHelper() {};
+
+ virtual GtkClipboard* getClipboard(Frame*) const = 0;
+ virtual GtkTargetList* getCopyTargetList(Frame*) const = 0;
+ virtual GtkTargetList* getPasteTargetList(Frame*) const = 0;
+};
+
+}
+
+#endif // PasteboardHelper_h
diff --git a/WebCore/platform/gtk/PlatformScreenGtk.cpp b/WebCore/platform/gtk/PlatformScreenGtk.cpp
new file mode 100644
index 0000000..9788253
--- /dev/null
+++ b/WebCore/platform/gtk/PlatformScreenGtk.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2008 Christian Dywan <christian@imendio.com>
+ * Copyright (C) 2008 Collabora Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PlatformScreen.h"
+
+#include "HostWindow.h"
+#include "NotImplemented.h"
+#include "ScrollView.h"
+#include "Widget.h"
+
+#include <gtk/gtk.h>
+
+#if PLATFORM(X11)
+#include <gdk/gdkx.h>
+#include <X11/Xatom.h>
+#endif
+
+namespace WebCore {
+
+int screenDepth(Widget* widget)
+{
+ GtkWidget* container = GTK_WIDGET(widget->root()->hostWindow()->platformWindow());
+ if (!container)
+ return 24;
+
+ GdkVisual* visual = gdk_drawable_get_visual(GDK_DRAWABLE(GTK_WIDGET(widget->root()->hostWindow()->platformWindow())->window));
+ return visual->depth;
+}
+
+int screenDepthPerComponent(Widget* widget)
+{
+ GtkWidget* container = GTK_WIDGET(widget->root()->hostWindow()->platformWindow());
+ if (!container)
+ return 8;
+
+ GdkVisual* visual = gdk_drawable_get_visual(GDK_DRAWABLE(GTK_WIDGET(widget->root()->hostWindow()->platformWindow())->window));
+ return visual->bits_per_rgb;
+}
+
+bool screenIsMonochrome(Widget* widget)
+{
+ GtkWidget* container = GTK_WIDGET(widget->root()->hostWindow()->platformWindow());
+ if (!container)
+ return false;
+
+ return screenDepth(widget) < 2;
+}
+
+FloatRect screenRect(Widget* widget)
+{
+ GtkWidget* container = GTK_WIDGET(widget->root()->hostWindow()->platformWindow());
+ if (!container)
+ return FloatRect();
+
+ GdkScreen* screen = gtk_widget_has_screen(container) ? gtk_widget_get_screen(container) : gdk_screen_get_default();
+ if (!screen)
+ return FloatRect();
+
+ gint monitor = gdk_screen_get_monitor_at_window(screen, GTK_WIDGET(container)->window);
+ GdkRectangle geometry;
+ gdk_screen_get_monitor_geometry(screen, monitor, &geometry);
+
+ return FloatRect(geometry.x, geometry.y, geometry.width, geometry.height);
+}
+
+FloatRect screenAvailableRect(Widget* widget)
+{
+#if PLATFORM(X11)
+ GtkWidget* container = GTK_WIDGET(widget->root()->hostWindow()->platformWindow());
+ if (!container)
+ return FloatRect();
+
+ if (!GTK_WIDGET_REALIZED(container))
+ return screenRect(widget);
+
+ GdkDrawable* rootWindow = GDK_DRAWABLE(gtk_widget_get_root_window(container));
+ GdkDisplay* display = gdk_drawable_get_display(rootWindow);
+ Atom xproperty = gdk_x11_get_xatom_by_name_for_display(display, "_NET_WORKAREA");
+
+ Atom retType;
+ int retFormat;
+ long *workAreaPos = NULL;
+ unsigned long retNItems;
+ unsigned long retAfter;
+ int xRes = XGetWindowProperty(GDK_DISPLAY_XDISPLAY(display), GDK_WINDOW_XWINDOW(rootWindow), xproperty,
+ 0, 4, FALSE, XA_CARDINAL, &retType, &retFormat, &retNItems, &retAfter, (guchar**)&workAreaPos);
+
+ FloatRect rect;
+ if (xRes == Success && workAreaPos != NULL && retType == XA_CARDINAL && retNItems == 4 && retFormat == 32) {
+ rect = FloatRect(workAreaPos[0], workAreaPos[1], workAreaPos[2], workAreaPos[3]);
+ // rect contains the available space in the whole screen not just in the monitor
+ // containing the widget, so we intersect it with the monitor rectangle.
+ rect.intersect(screenRect(widget));
+ } else
+ rect = screenRect(widget);
+
+ if (workAreaPos)
+ XFree(workAreaPos);
+
+ return rect;
+#else
+ return screenRect(widget);
+#endif
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/gtk/PopupMenuGtk.cpp b/WebCore/platform/gtk/PopupMenuGtk.cpp
new file mode 100644
index 0000000..85c5aa0
--- /dev/null
+++ b/WebCore/platform/gtk/PopupMenuGtk.cpp
@@ -0,0 +1,160 @@
+/*
+ * This file is part of the popup menu implementation for <select> elements in WebCore.
+ *
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2008 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "PopupMenu.h"
+
+#include "CString.h"
+#include "FrameView.h"
+#include "HostWindow.h"
+#include "NotImplemented.h"
+#include "PlatformString.h"
+#include <gtk/gtk.h>
+
+namespace WebCore {
+
+PopupMenu::PopupMenu(PopupMenuClient* client)
+ : m_popupClient(client)
+ , m_popup(0)
+{
+}
+
+PopupMenu::~PopupMenu()
+{
+ if (m_popup)
+ g_object_unref(m_popup);
+}
+
+void PopupMenu::show(const IntRect& rect, FrameView* view, int index)
+{
+ ASSERT(client());
+
+ if (!m_popup) {
+ m_popup = GTK_MENU(gtk_menu_new());
+#if GLIB_CHECK_VERSION(2,10,0)
+ g_object_ref_sink(G_OBJECT(m_popup));
+#else
+ g_object_ref(G_OBJECT(m_popup));
+ gtk_object_sink(GTK_OBJECT(m_popup));
+#endif
+ g_signal_connect(m_popup, "unmap", G_CALLBACK(menuUnmapped), this);
+ } else
+ gtk_container_foreach(GTK_CONTAINER(m_popup), reinterpret_cast<GtkCallback>(menuRemoveItem), this);
+
+ int x, y;
+ gdk_window_get_origin(GTK_WIDGET(view->hostWindow()->platformWindow())->window, &x, &y);
+ m_menuPosition = view->contentsToWindow(rect.location());
+ m_menuPosition = IntPoint(m_menuPosition.x() + x, m_menuPosition.y() + y + rect.height());
+ m_indexMap.clear();
+
+ const int size = client()->listSize();
+ for (int i = 0; i < size; ++i) {
+ GtkWidget* item;
+ if (client()->itemIsSeparator(i))
+ item = gtk_separator_menu_item_new();
+ else
+ item = gtk_menu_item_new_with_label(client()->itemText(i).utf8().data());
+
+ m_indexMap.add(item, i);
+ g_signal_connect(item, "activate", G_CALLBACK(menuItemActivated), this);
+
+ // FIXME: Apply the PopupMenuStyle from client()->itemStyle(i)
+ gtk_widget_set_sensitive(item, client()->itemIsEnabled(i));
+ gtk_menu_shell_append(GTK_MENU_SHELL(m_popup), item);
+ gtk_widget_show(item);
+ }
+
+ gtk_menu_set_active(m_popup, index);
+
+
+ // The size calls are directly copied from gtkcombobox.c which is LGPL
+ GtkRequisition requisition;
+ gtk_widget_set_size_request(GTK_WIDGET(m_popup), -1, -1);
+ gtk_widget_size_request(GTK_WIDGET(m_popup), &requisition);
+ gtk_widget_set_size_request(GTK_WIDGET(m_popup), MAX(rect.width(), requisition.width), -1);
+
+ GList* children = GTK_MENU_SHELL(m_popup)->children;
+ if (size)
+ for (int i = 0; i < size; i++) {
+ if (i > index)
+ break;
+
+ GtkWidget* item = reinterpret_cast<GtkWidget*>(children->data);
+ GtkRequisition itemRequisition;
+ gtk_widget_get_child_requisition(item, &itemRequisition);
+ m_menuPosition.setY(m_menuPosition.y() - itemRequisition.height);
+
+ children = g_list_next(children);
+ }
+ else
+ // Center vertically the empty popup in the combo box area
+ m_menuPosition.setY(m_menuPosition.y() - rect.height() / 2);
+
+ gtk_menu_popup(m_popup, NULL, NULL, reinterpret_cast<GtkMenuPositionFunc>(menuPositionFunction), this, 0, gtk_get_current_event_time());
+}
+
+void PopupMenu::hide()
+{
+ ASSERT(m_popup);
+ gtk_menu_popdown(m_popup);
+}
+
+void PopupMenu::updateFromElement()
+{
+ client()->setTextFromItem(client()->selectedIndex());
+}
+
+bool PopupMenu::itemWritingDirectionIsNatural()
+{
+ return true;
+}
+
+void PopupMenu::menuItemActivated(GtkMenuItem* item, PopupMenu* that)
+{
+ ASSERT(that->client());
+ ASSERT(that->m_indexMap.contains(GTK_WIDGET(item)));
+ that->client()->valueChanged(that->m_indexMap.get(GTK_WIDGET(item)));
+}
+
+void PopupMenu::menuUnmapped(GtkWidget*, PopupMenu* that)
+{
+ ASSERT(that->client());
+ that->client()->hidePopup();
+}
+
+void PopupMenu::menuPositionFunction(GtkMenu*, gint* x, gint* y, gboolean* pushIn, PopupMenu* that)
+{
+ *x = that->m_menuPosition.x();
+ *y = that->m_menuPosition.y();
+ *pushIn = true;
+}
+
+void PopupMenu::menuRemoveItem(GtkWidget* widget, PopupMenu* that)
+{
+ ASSERT(that->m_popup);
+ gtk_container_remove(GTK_CONTAINER(that->m_popup), widget);
+}
+
+}
+
diff --git a/WebCore/platform/gtk/RenderThemeGtk.cpp b/WebCore/platform/gtk/RenderThemeGtk.cpp
new file mode 100644
index 0000000..bf8b8d7
--- /dev/null
+++ b/WebCore/platform/gtk/RenderThemeGtk.cpp
@@ -0,0 +1,478 @@
+/*
+ * Copyright (C) 2007 Apple Inc.
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2008 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderThemeGtk.h"
+
+#include "AffineTransform.h"
+#include "GraphicsContext.h"
+#include "NotImplemented.h"
+#include "RenderObject.h"
+#include "gtkdrawing.h"
+
+#include <gdk/gdk.h>
+
+namespace WebCore {
+
+RenderTheme* theme()
+{
+ static RenderThemeGtk gtkTheme;
+ return &gtkTheme;
+}
+
+static bool mozGtkInitialized = false;
+
+RenderThemeGtk::RenderThemeGtk()
+ : m_gtkWindow(0)
+ , m_gtkContainer(0)
+ , m_gtkEntry(0)
+ , m_gtkTreeView(0)
+{
+ if (!mozGtkInitialized) {
+ mozGtkInitialized = true;
+ moz_gtk_init();
+ }
+}
+
+static bool supportsFocus(ControlPart appearance)
+{
+ switch (appearance) {
+ case PushButtonPart:
+ case ButtonPart:
+ case TextFieldPart:
+ case TextAreaPart:
+ case SearchFieldPart:
+ case MenulistPart:
+ case RadioPart:
+ case CheckboxPart:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool RenderThemeGtk::supportsFocusRing(const RenderStyle* style) const
+{
+ return supportsFocus(style->appearance());
+}
+
+bool RenderThemeGtk::controlSupportsTints(const RenderObject* o) const
+{
+ return isEnabled(o);
+}
+
+int RenderThemeGtk::baselinePosition(const RenderObject* o) const
+{
+ // FIXME: This strategy is possibly incorrect for the GTK+ port.
+ if (o->style()->appearance() == CheckboxPart ||
+ o->style()->appearance() == RadioPart)
+ return o->marginTop() + o->height() - 2;
+ return RenderTheme::baselinePosition(o);
+}
+
+static GtkTextDirection gtkTextDirection(TextDirection direction)
+{
+ switch (direction) {
+ case RTL:
+ return GTK_TEXT_DIR_RTL;
+ case LTR:
+ return GTK_TEXT_DIR_LTR;
+ default:
+ return GTK_TEXT_DIR_NONE;
+ }
+}
+
+static void adjustMozStyle(RenderStyle* style, GtkThemeWidgetType type)
+{
+ gint left, top, right, bottom;
+ GtkTextDirection direction = gtkTextDirection(style->direction());
+ gboolean inhtml = true;
+
+ if (moz_gtk_get_widget_border(type, &left, &top, &right, &bottom, direction, inhtml) != MOZ_GTK_SUCCESS)
+ return;
+
+ // FIXME: This approach is likely to be incorrect. See other ports and layout tests to see the problem.
+ const int xpadding = 1;
+ const int ypadding = 1;
+
+ style->setPaddingLeft(Length(xpadding + left, Fixed));
+ style->setPaddingTop(Length(ypadding + top, Fixed));
+ style->setPaddingRight(Length(xpadding + right, Fixed));
+ style->setPaddingBottom(Length(ypadding + bottom, Fixed));
+}
+
+static void setMozState(RenderTheme* theme, GtkWidgetState* state, RenderObject* o)
+{
+ state->active = theme->isPressed(o);
+ state->focused = theme->isFocused(o);
+ state->inHover = theme->isHovered(o);
+ // FIXME: Disabled does not always give the correct appearance for ReadOnly
+ state->disabled = !theme->isEnabled(o) || theme->isReadOnlyControl(o);
+ state->isDefault = false;
+ state->canDefault = false;
+ state->depressed = false;
+}
+
+static bool paintMozWidget(RenderTheme* theme, GtkThemeWidgetType type, RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ // No GdkWindow to render to, so return true to fall back
+ if (!i.context->gdkDrawable())
+ return true;
+
+ // Painting is disabled so just claim to have succeeded
+ if (i.context->paintingDisabled())
+ return false;
+
+ GtkWidgetState mozState;
+ setMozState(theme, &mozState, o);
+
+ int flags;
+
+ // We might want to make setting flags the caller's job at some point rather than doing it here.
+ switch (type) {
+ case MOZ_GTK_BUTTON:
+ flags = GTK_RELIEF_NORMAL;
+ break;
+ case MOZ_GTK_CHECKBUTTON:
+ case MOZ_GTK_RADIOBUTTON:
+ flags = theme->isChecked(o);
+ break;
+ default:
+ flags = 0;
+ break;
+ }
+
+ AffineTransform ctm = i.context->getCTM();
+
+ IntPoint pos = ctm.mapPoint(rect.location());
+ GdkRectangle gdkRect = IntRect(pos.x(), pos.y(), rect.width(), rect.height());
+ GtkTextDirection direction = gtkTextDirection(o->style()->direction());
+
+#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,4,0)
+ // Find the clip rectangle
+ cairo_t *cr = i.context->platformContext();
+ double clipX1, clipX2, clipY1, clipY2;
+ cairo_clip_extents(cr, &clipX1, &clipY1, &clipX2, &clipY2);
+
+ GdkRectangle gdkClipRect;
+ gdkClipRect.width = clipX2 - clipX1;
+ gdkClipRect.height = clipY2 - clipY1;
+ IntPoint clipPos = ctm.mapPoint(IntPoint(clipX1, clipY1));
+ gdkClipRect.x = clipPos.x();
+ gdkClipRect.y = clipPos.y();
+
+ gdk_rectangle_intersect(&gdkRect, &gdkClipRect, &gdkClipRect);
+#else
+ GdkRectangle gdkClipRect = gdkRect;
+#endif
+
+ return moz_gtk_widget_paint(type, i.context->gdkDrawable(), &gdkRect, &gdkClipRect, &mozState, flags, direction) != MOZ_GTK_SUCCESS;
+}
+
+static void setButtonPadding(RenderStyle* style)
+{
+ // FIXME: This looks incorrect.
+ const int padding = 8;
+ style->setPaddingLeft(Length(padding, Fixed));
+ style->setPaddingRight(Length(padding, Fixed));
+ style->setPaddingTop(Length(padding / 2, Fixed));
+ style->setPaddingBottom(Length(padding / 2, Fixed));
+}
+
+static void setToggleSize(RenderStyle* style, ControlPart appearance)
+{
+ // The width and height are both specified, so we shouldn't change them.
+ if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
+ return;
+
+ // FIXME: This is probably not correct use of indicator_size and indicator_spacing.
+ gint indicator_size, indicator_spacing;
+
+ switch (appearance) {
+ case CheckboxPart:
+ if (moz_gtk_checkbox_get_metrics(&indicator_size, &indicator_spacing) != MOZ_GTK_SUCCESS)
+ return;
+ break;
+ case RadioPart:
+ if (moz_gtk_radio_get_metrics(&indicator_size, &indicator_spacing) != MOZ_GTK_SUCCESS)
+ return;
+ break;
+ default:
+ return;
+ }
+
+ // Other ports hard-code this to 13, but GTK+ users tend to demand the native look.
+ // It could be made a configuration option values other than 13 actually break site compatibility.
+ int length = indicator_size + indicator_spacing;
+ if (style->width().isIntrinsicOrAuto())
+ style->setWidth(Length(length, Fixed));
+
+ if (style->height().isAuto())
+ style->setHeight(Length(length, Fixed));
+}
+
+void RenderThemeGtk::setCheckboxSize(RenderStyle* style) const
+{
+ setToggleSize(style, RadioPart);
+}
+
+bool RenderThemeGtk::paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return paintMozWidget(this, MOZ_GTK_CHECKBUTTON, o, i, rect);
+}
+
+void RenderThemeGtk::setRadioSize(RenderStyle* style) const
+{
+ setToggleSize(style, RadioPart);
+}
+
+bool RenderThemeGtk::paintRadio(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return paintMozWidget(this, MOZ_GTK_RADIOBUTTON, o, i, rect);
+}
+
+void RenderThemeGtk::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, WebCore::Element* e) const
+{
+ // FIXME: Is this condition necessary?
+ if (style->appearance() == PushButtonPart) {
+ style->resetBorder();
+ style->setHeight(Length(Auto));
+ style->setWhiteSpace(PRE);
+ setButtonPadding(style);
+ } else {
+ // FIXME: This should not be hard-coded.
+ style->setMinHeight(Length(14, Fixed));
+ style->resetBorderTop();
+ style->resetBorderBottom();
+ }
+}
+
+bool RenderThemeGtk::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return paintMozWidget(this, MOZ_GTK_BUTTON, o, i, rect);
+}
+
+void RenderThemeGtk::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, WebCore::Element* e) const
+{
+ style->resetBorder();
+ style->resetPadding();
+ style->setHeight(Length(Auto));
+ style->setWhiteSpace(PRE);
+ adjustMozStyle(style, MOZ_GTK_DROPDOWN);
+}
+
+bool RenderThemeGtk::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return paintMozWidget(this, MOZ_GTK_DROPDOWN, o, i, rect);
+}
+
+void RenderThemeGtk::adjustTextFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ style->resetBorder();
+ style->resetPadding();
+ style->setHeight(Length(Auto));
+ style->setWhiteSpace(PRE);
+ adjustMozStyle(style, MOZ_GTK_ENTRY);
+}
+
+bool RenderThemeGtk::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return paintMozWidget(this, MOZ_GTK_ENTRY, o, i, rect);
+}
+
+void RenderThemeGtk::adjustTextAreaStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ adjustTextFieldStyle(selector, style, e);
+}
+
+bool RenderThemeGtk::paintTextArea(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ return paintTextField(o, i, r);
+}
+
+void RenderThemeGtk::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ adjustSearchFieldCancelButtonStyle(selector, style, e);
+}
+
+bool RenderThemeGtk::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return paintMozWidget(this, MOZ_GTK_DROPDOWN_ARROW, o, i, rect);
+}
+
+void RenderThemeGtk::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ style->resetBorder();
+ style->resetPadding();
+
+ // FIXME: This should not be hard-coded.
+ IntSize size = IntSize(14, 14);
+ style->setWidth(Length(size.width(), Fixed));
+ style->setHeight(Length(size.height(), Fixed));
+}
+
+bool RenderThemeGtk::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return paintMozWidget(this, MOZ_GTK_CHECKMENUITEM, o, i, rect);
+}
+
+void RenderThemeGtk::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ style->resetBorder();
+ style->resetPadding();
+
+ // FIXME: This should not be hard-coded.
+ IntSize size = IntSize(14, 14);
+ style->setWidth(Length(size.width(), Fixed));
+ style->setHeight(Length(size.height(), Fixed));
+}
+
+bool RenderThemeGtk::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return paintMozWidget(this, MOZ_GTK_CHECKMENUITEM, o, i, rect);
+}
+
+void RenderThemeGtk::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ adjustTextFieldStyle(selector, style, e);
+}
+
+bool RenderThemeGtk::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return paintTextField(o, i, rect);
+}
+
+Color RenderThemeGtk::platformActiveSelectionBackgroundColor() const
+{
+ GtkWidget* widget = gtkEntry();
+ return widget->style->base[GTK_STATE_SELECTED];
+}
+
+Color RenderThemeGtk::platformInactiveSelectionBackgroundColor() const
+{
+ GtkWidget* widget = gtkEntry();
+ return widget->style->base[GTK_STATE_ACTIVE];
+}
+
+Color RenderThemeGtk::platformActiveSelectionForegroundColor() const
+{
+ GtkWidget* widget = gtkEntry();
+ return widget->style->text[GTK_STATE_SELECTED];
+}
+
+Color RenderThemeGtk::platformInactiveSelectionForegroundColor() const
+{
+ GtkWidget* widget = gtkEntry();
+ return widget->style->text[GTK_STATE_ACTIVE];
+}
+
+Color RenderThemeGtk::activeListBoxSelectionBackgroundColor() const
+{
+ GtkWidget* widget = gtkTreeView();
+ return widget->style->base[GTK_STATE_SELECTED];
+}
+
+Color RenderThemeGtk::inactiveListBoxSelectionBackgroundColor() const
+{
+ GtkWidget* widget = gtkTreeView();
+ return widget->style->base[GTK_STATE_ACTIVE];
+}
+
+Color RenderThemeGtk::activeListBoxSelectionForegroundColor() const
+{
+ GtkWidget* widget = gtkTreeView();
+ return widget->style->text[GTK_STATE_SELECTED];
+}
+
+Color RenderThemeGtk::inactiveListBoxSelectionForegroundColor() const
+{
+ GtkWidget* widget = gtkTreeView();
+ return widget->style->text[GTK_STATE_ACTIVE];
+}
+
+double RenderThemeGtk::caretBlinkFrequency() const
+{
+ GtkSettings* settings = gtk_settings_get_default();
+
+ gboolean shouldBlink;
+ gint time;
+
+ g_object_get(settings, "gtk-cursor-blink", &shouldBlink, "gtk-cursor-blink-time", &time, NULL);
+
+ if (!shouldBlink)
+ return 0;
+
+ return time / 2000.;
+}
+
+void RenderThemeGtk::systemFont(int, FontDescription&) const
+{
+ // If you remove this notImplemented(), replace it with an comment that explains why.
+ notImplemented();
+}
+
+static void gtkStyleSetCallback(GtkWidget* widget, GtkStyle* previous, RenderTheme* renderTheme)
+{
+ // FIXME: Make sure this function doesn't get called many times for a single GTK+ style change signal.
+ renderTheme->platformColorsDidChange();
+}
+
+GtkContainer* RenderThemeGtk::gtkContainer() const
+{
+ if (m_gtkContainer)
+ return m_gtkContainer;
+
+ m_gtkWindow = gtk_window_new(GTK_WINDOW_POPUP);
+ m_gtkContainer = GTK_CONTAINER(gtk_fixed_new());
+ gtk_container_add(GTK_CONTAINER(m_gtkWindow), GTK_WIDGET(m_gtkContainer));
+ gtk_widget_realize(m_gtkWindow);
+
+ return m_gtkContainer;
+}
+
+GtkWidget* RenderThemeGtk::gtkEntry() const
+{
+ if (m_gtkEntry)
+ return m_gtkEntry;
+
+ m_gtkEntry = gtk_entry_new();
+ g_signal_connect(m_gtkEntry, "style-set", G_CALLBACK(gtkStyleSetCallback), theme());
+ gtk_container_add(gtkContainer(), m_gtkEntry);
+ gtk_widget_realize(m_gtkEntry);
+
+ return m_gtkEntry;
+}
+
+GtkWidget* RenderThemeGtk::gtkTreeView() const
+{
+ if (m_gtkTreeView)
+ return m_gtkTreeView;
+
+ m_gtkTreeView = gtk_tree_view_new();
+ g_signal_connect(m_gtkTreeView, "style-set", G_CALLBACK(gtkStyleSetCallback), theme());
+ gtk_container_add(gtkContainer(), m_gtkTreeView);
+ gtk_widget_realize(m_gtkTreeView);
+
+ return m_gtkTreeView;
+}
+
+}
diff --git a/WebCore/platform/gtk/RenderThemeGtk.h b/WebCore/platform/gtk/RenderThemeGtk.h
new file mode 100644
index 0000000..dda8bc8
--- /dev/null
+++ b/WebCore/platform/gtk/RenderThemeGtk.h
@@ -0,0 +1,128 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderThemeGdk_h
+#define RenderThemeGdk_h
+
+#include "RenderTheme.h"
+
+#include <gtk/gtk.h>
+
+namespace WebCore {
+
+class RenderThemeGtk : public RenderTheme {
+public:
+ RenderThemeGtk();
+
+ // A method asking if the theme's controls actually care about redrawing when hovered.
+ virtual bool supportsHover(const RenderStyle* style) const { return true; }
+
+ // A method asking if the theme is able to draw the focus ring.
+ virtual bool supportsFocusRing(const RenderStyle*) const;
+
+ // A method asking if the control changes its tint when the window has focus or not.
+ virtual bool controlSupportsTints(const RenderObject*) const;
+
+ // A general method asking if any control tinting is supported at all.
+ virtual bool supportsControlTints() const { return true; }
+
+ // A method to obtain the baseline position for a "leaf" control. This will only be used if a baseline
+ // position cannot be determined by examining child content. Checkboxes and radio buttons are examples of
+ // controls that need to do this.
+ virtual int baselinePosition(const RenderObject*) const;
+
+ // The platform selection color.
+ virtual Color platformActiveSelectionBackgroundColor() const;
+ virtual Color platformInactiveSelectionBackgroundColor() const;
+ virtual Color platformActiveSelectionForegroundColor() const;
+ virtual Color platformInactiveSelectionForegroundColor() const;
+
+ // List Box selection color
+ virtual Color activeListBoxSelectionBackgroundColor() const;
+ virtual Color activeListBoxSelectionForegroundColor() const;
+ virtual Color inactiveListBoxSelectionBackgroundColor() const;
+ virtual Color inactiveListBoxSelectionForegroundColor() const;
+
+ virtual double caretBlinkFrequency() const;
+
+ // System fonts.
+ virtual void systemFont(int propId, FontDescription&) const;
+
+protected:
+ virtual bool paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r);
+ virtual void setCheckboxSize(RenderStyle* style) const;
+
+ virtual bool paintRadio(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r);
+ virtual void setRadioSize(RenderStyle* style) const;
+
+ virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintTextField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintTextArea(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintMenuList(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintSearchFieldResultsDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintSearchField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintSearchFieldResultsButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintSearchFieldCancelButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+
+private:
+ /*
+ * hold the state
+ */
+ GtkWidget* gtkEntry() const;
+ GtkWidget* gtkTreeView() const;
+
+ /*
+ * unmapped GdkWindow having a container. This is holding all
+ * our fake widgets
+ */
+ GtkContainer* gtkContainer() const;
+
+private:
+ mutable GtkWidget* m_gtkWindow;
+ mutable GtkContainer* m_gtkContainer;
+ mutable GtkWidget* m_gtkEntry;
+ mutable GtkWidget* m_gtkTreeView;
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/gtk/ScrollViewGtk.cpp b/WebCore/platform/gtk/ScrollViewGtk.cpp
new file mode 100644
index 0000000..e1316ee
--- /dev/null
+++ b/WebCore/platform/gtk/ScrollViewGtk.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ * Copyright (C) 2008 Collabora Ltd.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ScrollView.h"
+
+#include "FloatRect.h"
+#include "GraphicsContext.h"
+#include "HostWindow.h"
+#include "IntRect.h"
+#include "NotImplemented.h"
+#include "PlatformMouseEvent.h"
+#include "PlatformWheelEvent.h"
+#include "ScrollbarGtk.h"
+#include "ScrollbarTheme.h"
+
+#include <gtk/gtk.h>
+
+using namespace std;
+
+namespace WebCore {
+
+static void adjustmentChanged(GtkAdjustment* adjustment, gpointer _that)
+{
+ ScrollView* that = reinterpret_cast<ScrollView*>(_that);
+
+ // Figure out if we really moved.
+ IntSize newOffset = that->scrollOffset();
+ if (adjustment == that->m_horizontalAdjustment)
+ newOffset.setWidth(static_cast<int>(gtk_adjustment_get_value(adjustment)));
+ else if (adjustment == that->m_verticalAdjustment)
+ newOffset.setHeight(static_cast<int>(gtk_adjustment_get_value(adjustment)));
+
+ IntSize scrollDelta = newOffset - that->scrollOffset();
+ if (scrollDelta == IntSize())
+ return;
+ that->setScrollOffset(newOffset);
+
+ if (that->scrollbarsSuppressed())
+ return;
+
+ that->scrollContents(scrollDelta);
+}
+
+void ScrollView::platformInit()
+{
+ m_horizontalAdjustment = 0;
+ m_verticalAdjustment = 0;
+}
+
+void ScrollView::platformDestroy()
+{
+ if (m_horizontalAdjustment) {
+ g_signal_handlers_disconnect_by_func(G_OBJECT(m_horizontalAdjustment), (gpointer)adjustmentChanged, this);
+ g_object_unref(m_horizontalAdjustment);
+ }
+
+ if (m_verticalAdjustment) {
+ g_signal_handlers_disconnect_by_func(G_OBJECT(m_verticalAdjustment), (gpointer)adjustmentChanged, this);
+ g_object_unref(m_verticalAdjustment);
+ }
+}
+
+/*
+ * The following is assumed:
+ * (hadj && vadj) || (!hadj && !vadj)
+ */
+void ScrollView::setGtkAdjustments(GtkAdjustment* hadj, GtkAdjustment* vadj)
+{
+ ASSERT(!hadj == !vadj);
+
+ if (m_horizontalAdjustment) {
+ g_signal_handlers_disconnect_by_func(G_OBJECT(m_horizontalAdjustment), (gpointer)adjustmentChanged, this);
+ g_signal_handlers_disconnect_by_func(G_OBJECT(m_verticalAdjustment), (gpointer)adjustmentChanged, this);
+ g_object_unref(m_horizontalAdjustment);
+ g_object_unref(m_verticalAdjustment);
+ }
+
+ m_horizontalAdjustment = hadj;
+ m_verticalAdjustment = vadj;
+
+ if (m_horizontalAdjustment) {
+ g_signal_connect(m_horizontalAdjustment, "value-changed", G_CALLBACK(adjustmentChanged), this);
+ g_signal_connect(m_verticalAdjustment, "value-changed", G_CALLBACK(adjustmentChanged), this);
+
+ /*
+ * disable the scrollbars (if we have any) as the GtkAdjustment over
+ */
+ setHasVerticalScrollbar(false);
+ setHasHorizontalScrollbar(false);
+
+ g_object_ref(m_horizontalAdjustment);
+ g_object_ref(m_verticalAdjustment);
+ }
+
+ updateScrollbars(m_scrollOffset);
+}
+
+void ScrollView::platformAddChild(Widget* child)
+{
+ if (!GTK_IS_SOCKET(child->platformWidget()))
+ gtk_container_add(GTK_CONTAINER(hostWindow()->platformWindow()), child->platformWidget());
+}
+
+void ScrollView::platformRemoveChild(Widget* child)
+{
+ GtkWidget* parent;
+
+ // HostWindow can be NULL here. If that's the case
+ // let's grab the child's parent instead.
+ if (hostWindow())
+ parent = GTK_WIDGET(hostWindow()->platformWindow());
+ else
+ parent = GTK_WIDGET(child->platformWidget()->parent);
+
+ if (GTK_IS_CONTAINER(parent) && parent == child->platformWidget()->parent)
+ gtk_container_remove(GTK_CONTAINER(parent), child->platformWidget());
+}
+
+bool ScrollView::platformHandleHorizontalAdjustment(const IntSize& scroll)
+{
+ if (m_horizontalAdjustment) {
+ m_horizontalAdjustment->page_size = visibleWidth();
+ m_horizontalAdjustment->step_increment = visibleWidth() / 10.0;
+ m_horizontalAdjustment->page_increment = visibleWidth() * 0.9;
+ m_horizontalAdjustment->lower = 0;
+ m_horizontalAdjustment->upper = contentsWidth();
+ gtk_adjustment_changed(m_horizontalAdjustment);
+
+ if (m_scrollOffset.width() != scroll.width()) {
+ m_horizontalAdjustment->value = scroll.width();
+ gtk_adjustment_value_changed(m_horizontalAdjustment);
+ }
+ return true;
+ }
+ return false;
+}
+
+bool ScrollView::platformHandleVerticalAdjustment(const IntSize& scroll)
+{
+ if (m_verticalAdjustment) {
+ m_verticalAdjustment->page_size = visibleHeight();
+ m_verticalAdjustment->step_increment = visibleHeight() / 10.0;
+ m_verticalAdjustment->page_increment = visibleHeight() * 0.9;
+ m_verticalAdjustment->lower = 0;
+ m_verticalAdjustment->upper = contentsHeight();
+ gtk_adjustment_changed(m_verticalAdjustment);
+
+ if (m_scrollOffset.height() != scroll.height()) {
+ m_verticalAdjustment->value = scroll.height();
+ gtk_adjustment_value_changed(m_verticalAdjustment);
+ }
+ return true;
+ }
+ return false;
+}
+
+bool ScrollView::platformHasHorizontalAdjustment() const
+{
+ return m_horizontalAdjustment != 0;
+}
+
+bool ScrollView::platformHasVerticalAdjustment() const
+{
+ return m_verticalAdjustment != 0;
+}
+
+}
diff --git a/WebCore/platform/gtk/ScrollbarGtk.cpp b/WebCore/platform/gtk/ScrollbarGtk.cpp
new file mode 100644
index 0000000..099895d
--- /dev/null
+++ b/WebCore/platform/gtk/ScrollbarGtk.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2007 Holger Hans Peter Freyther zecke@selfish.org
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "ScrollbarGtk.h"
+
+#include "IntRect.h"
+#include "GraphicsContext.h"
+#include "FrameView.h"
+#include "NotImplemented.h"
+#include "ScrollbarTheme.h"
+#include "gtkdrawing.h"
+
+#include <gtk/gtk.h>
+
+using namespace WebCore;
+
+PassRefPtr<Scrollbar> Scrollbar::createNativeScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize size)
+{
+ return adoptRef(new ScrollbarGtk(client, orientation, size));
+}
+
+static gboolean gtkScrollEventCallback(GtkWidget* widget, GdkEventScroll* event, ScrollbarGtk*)
+{
+ /* Scroll only if our parent rejects the scroll event. The rationale for
+ * this is that we want the main frame to scroll when we move the mouse
+ * wheel over a child scrollbar in most cases. */
+ return gtk_widget_event(gtk_widget_get_parent(widget), reinterpret_cast<GdkEvent*>(event));
+}
+
+ScrollbarGtk::ScrollbarGtk(ScrollbarClient* client, ScrollbarOrientation orientation,
+ ScrollbarControlSize controlSize)
+ : Scrollbar(client, orientation, controlSize)
+ , m_adjustment(GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)))
+{
+ GtkScrollbar* scrollBar = orientation == HorizontalScrollbar ?
+ GTK_SCROLLBAR(::gtk_hscrollbar_new(m_adjustment)) :
+ GTK_SCROLLBAR(::gtk_vscrollbar_new(m_adjustment));
+ gtk_widget_show(GTK_WIDGET(scrollBar));
+ g_object_ref(G_OBJECT(scrollBar));
+ g_signal_connect(G_OBJECT(scrollBar), "value-changed", G_CALLBACK(ScrollbarGtk::gtkValueChanged), this);
+ g_signal_connect(G_OBJECT(scrollBar), "scroll-event", G_CALLBACK(gtkScrollEventCallback), this);
+
+ setPlatformWidget(GTK_WIDGET(scrollBar));
+
+ /*
+ * assign a sane default width and height to the Scrollbar, otherwise
+ * we will end up with a 0 width scrollbar.
+ */
+ resize(ScrollbarTheme::nativeTheme()->scrollbarThickness(),
+ ScrollbarTheme::nativeTheme()->scrollbarThickness());
+}
+
+ScrollbarGtk::~ScrollbarGtk()
+{
+ /*
+ * the Widget does not take over ownership.
+ */
+ g_signal_handlers_disconnect_by_func(G_OBJECT(platformWidget()), (gpointer)ScrollbarGtk::gtkValueChanged, this);
+ g_signal_handlers_disconnect_by_func(G_OBJECT(platformWidget()), (gpointer)gtkScrollEventCallback, this);
+ g_object_unref(G_OBJECT(platformWidget()));
+}
+
+void ScrollbarGtk::frameRectsChanged() const
+{
+ if (!parent() || !parent()->isScrollViewScrollbar(this))
+ return;
+
+ IntPoint loc = parent()->convertToContainingWindow(frameRect().location());
+
+ // Don't allow the allocation size to be negative
+ IntSize sz = frameRect().size();
+ sz.clampNegativeToZero();
+
+ GtkAllocation allocation = { loc.x(), loc.y(), sz.width(), sz.height() };
+ gtk_widget_size_allocate(platformWidget(), &allocation);
+}
+
+void ScrollbarGtk::updateThumbPosition()
+{
+ if (m_adjustment->value != m_currentPos) {
+ m_adjustment->value = m_currentPos;
+ gtk_adjustment_value_changed(m_adjustment);
+ }
+}
+
+void ScrollbarGtk::updateThumbProportion()
+{
+ m_adjustment->step_increment = m_lineStep;
+ m_adjustment->page_increment = m_pageStep;
+ m_adjustment->page_size = m_visibleSize;
+ m_adjustment->upper = m_totalSize;
+ gtk_adjustment_changed(m_adjustment);
+}
+
+void ScrollbarGtk::setFrameRect(const IntRect& rect)
+{
+ Widget::setFrameRect(rect);
+ frameRectsChanged();
+}
+
+void ScrollbarGtk::frameRectsChanged()
+{
+ if (!parent())
+ return;
+
+ ASSERT(parent()->isFrameView());
+
+ FrameView* frameView = static_cast<FrameView*>(parent());
+ IntRect windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size());
+
+ IntSize sz = frameRect().size();
+ sz.clampNegativeToZero();
+
+ GtkAllocation allocation = { windowRect.x(), windowRect.y(), sz.width(), sz.height() };
+ gtk_widget_size_allocate(platformWidget(), &allocation);
+}
+
+void ScrollbarGtk::gtkValueChanged(GtkAdjustment*, ScrollbarGtk* that)
+{
+ that->setValue(static_cast<int>(gtk_adjustment_get_value(that->m_adjustment)));
+}
+
+void ScrollbarGtk::setEnabled(bool shouldEnable)
+{
+ if (enabled() == shouldEnable)
+ return;
+
+ Scrollbar::setEnabled(shouldEnable);
+ if (platformWidget())
+ gtk_widget_set_sensitive(platformWidget(), shouldEnable);
+}
+
+
+
diff --git a/WebCore/platform/gtk/ScrollbarGtk.h b/WebCore/platform/gtk/ScrollbarGtk.h
new file mode 100644
index 0000000..50e9184
--- /dev/null
+++ b/WebCore/platform/gtk/ScrollbarGtk.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ScrollbarGtk_h
+#define ScrollbarGtk_h
+
+#include "Scrollbar.h"
+#include <wtf/PassRefPtr.h>
+
+typedef struct _GtkAdjustment GtkAdjustment;
+
+namespace WebCore {
+
+class ScrollbarGtk : public Scrollbar {
+public:
+ friend class Scrollbar;
+
+ virtual ~ScrollbarGtk();
+
+ virtual void setFrameRect(const IntRect&);
+
+ virtual bool handleMouseMoveEvent(const PlatformMouseEvent&) { return false; }
+ virtual bool handleMouseOutEvent(const PlatformMouseEvent&) { return false; }
+ virtual bool handleMousePressEvent(const PlatformMouseEvent&) { return false; }
+ virtual bool handleMouseReleaseEvent(const PlatformMouseEvent&) { return false; }
+
+ virtual void setEnabled(bool);
+
+ virtual void frameRectsChanged() const;
+
+protected:
+ ScrollbarGtk(ScrollbarClient*, ScrollbarOrientation, ScrollbarControlSize);
+
+ virtual void updateThumbPosition();
+ virtual void updateThumbProportion();
+ virtual void frameRectsChanged();
+
+private:
+ static void gtkValueChanged(GtkAdjustment*, ScrollbarGtk*);
+ GtkAdjustment* m_adjustment;
+};
+
+}
+
+#endif // ScrollbarGtk_h
diff --git a/WebCore/platform/gtk/ScrollbarThemeGtk.cpp b/WebCore/platform/gtk/ScrollbarThemeGtk.cpp
new file mode 100644
index 0000000..fee2c70
--- /dev/null
+++ b/WebCore/platform/gtk/ScrollbarThemeGtk.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ScrollbarThemeGtk.h"
+
+#include "gtkdrawing.h"
+#include <gtk/gtk.h>
+
+namespace WebCore {
+
+ScrollbarTheme* ScrollbarTheme::nativeTheme()
+{
+ static ScrollbarThemeGtk theme;
+ return &theme;
+}
+
+ScrollbarThemeGtk::~ScrollbarThemeGtk()
+{
+}
+
+int ScrollbarThemeGtk::scrollbarThickness(ScrollbarControlSize controlSize)
+{
+ static int size;
+ if (!size) {
+ MozGtkScrollbarMetrics metrics;
+ moz_gtk_get_scrollbar_metrics(&metrics);
+ size = metrics.slider_width;
+ }
+ return size;
+}
+
+}
+
diff --git a/WebCore/platform/gtk/ScrollbarThemeGtk.h b/WebCore/platform/gtk/ScrollbarThemeGtk.h
new file mode 100644
index 0000000..21ccb43
--- /dev/null
+++ b/WebCore/platform/gtk/ScrollbarThemeGtk.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ScrollbarThemeGtk_h
+#define ScrollbarThemeGtk_h
+
+#include "ScrollbarTheme.h"
+
+namespace WebCore {
+
+class ScrollbarThemeGtk : public ScrollbarTheme {
+public:
+ virtual ~ScrollbarThemeGtk();
+
+ virtual int scrollbarThickness(ScrollbarControlSize = RegularScrollbar);
+};
+
+}
+#endif
diff --git a/WebCore/platform/gtk/SearchPopupMenuGtk.cpp b/WebCore/platform/gtk/SearchPopupMenuGtk.cpp
new file mode 100644
index 0000000..fbaa527
--- /dev/null
+++ b/WebCore/platform/gtk/SearchPopupMenuGtk.cpp
@@ -0,0 +1,46 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "SearchPopupMenu.h"
+
+#include "NotImplemented.h"
+
+namespace WebCore {
+
+SearchPopupMenu::SearchPopupMenu(PopupMenuClient* client)
+ : PopupMenu(client)
+{
+ notImplemented();
+}
+
+void SearchPopupMenu::saveRecentSearches(const AtomicString&, const Vector<String>&)
+{
+ notImplemented();
+}
+
+void SearchPopupMenu::loadRecentSearches(const AtomicString&, Vector<String>&)
+{
+ notImplemented();
+}
+
+bool SearchPopupMenu::enabled()
+{
+ notImplemented();
+ return false;
+}
+
+}
diff --git a/WebCore/platform/gtk/SharedBufferGtk.cpp b/WebCore/platform/gtk/SharedBufferGtk.cpp
new file mode 100644
index 0000000..783fec6
--- /dev/null
+++ b/WebCore/platform/gtk/SharedBufferGtk.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "SharedBuffer.h"
+
+#include "CString.h"
+#include "FileSystem.h"
+
+#include <glib.h>
+
+
+namespace WebCore {
+
+PassRefPtr<SharedBuffer> SharedBuffer::createWithContentsOfFile(const String& filePath)
+{
+ if (filePath.isEmpty())
+ return 0;
+
+ gchar* filename = filenameFromString(filePath);
+ gchar* contents;
+ gsize size;
+ GError* error = 0;
+ if (!g_file_get_contents(filename, &contents, &size, &error)) {
+ LOG_ERROR("Failed to fully read contents of file %s - %s", filenameForDisplay(filePath).utf8().data(), error->message);
+ g_error_free(error);
+ g_free(filename);
+ return 0;
+ }
+
+ RefPtr<SharedBuffer> result = SharedBuffer::create(contents, size);
+ g_free(filename);
+ g_free(contents);
+
+ return result.release();
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/gtk/SharedTimerGtk.cpp b/WebCore/platform/gtk/SharedTimerGtk.cpp
new file mode 100644
index 0000000..e0a5b60
--- /dev/null
+++ b/WebCore/platform/gtk/SharedTimerGtk.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SharedTimer.h"
+
+#include "SystemTime.h"
+#include <wtf/Assertions.h>
+#include <glib.h>
+
+namespace WebCore {
+
+static guint sharedTimer;
+static void (*sharedTimerFiredFunction)();
+
+void setSharedTimerFiredFunction(void (*f)())
+{
+ sharedTimerFiredFunction = f;
+}
+
+static gboolean timeout_cb(gpointer)
+{
+ if (sharedTimerFiredFunction)
+ sharedTimerFiredFunction();
+ return FALSE;
+}
+
+void setSharedTimerFireTime(double fireTime)
+{
+ ASSERT(sharedTimerFiredFunction);
+
+ double interval = fireTime - currentTime();
+ guint intervalInMS;
+ if (interval < 0)
+ intervalInMS = 0;
+ else {
+ interval *= 1000;
+ intervalInMS = (guint)interval;
+ }
+
+ stopSharedTimer();
+ if (intervalInMS == 0)
+ sharedTimer = g_idle_add(timeout_cb, NULL);
+ else
+ sharedTimer = g_timeout_add_full(G_PRIORITY_DEFAULT, intervalInMS, timeout_cb, NULL, NULL);
+}
+
+void stopSharedTimer()
+{
+ gboolean s = FALSE;
+ if (sharedTimer == 0)
+ return;
+
+ s = g_source_remove(sharedTimer);
+ ASSERT(s);
+ sharedTimer = 0;
+}
+
+}
diff --git a/WebCore/platform/gtk/SoundGtk.cpp b/WebCore/platform/gtk/SoundGtk.cpp
new file mode 100644
index 0000000..2f7316c
--- /dev/null
+++ b/WebCore/platform/gtk/SoundGtk.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "Sound.h"
+
+#include <gdk/gdk.h>
+
+namespace WebCore {
+
+void systemBeep()
+{
+ gdk_beep();
+}
+
+}
+
+// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/gtk/SystemTimeGtk.cpp b/WebCore/platform/gtk/SystemTimeGtk.cpp
new file mode 100644
index 0000000..9d26d41
--- /dev/null
+++ b/WebCore/platform/gtk/SystemTimeGtk.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include <glib.h>
+
+namespace WebCore {
+
+double currentTime()
+{
+ GTimeVal now;
+ g_get_current_time(&now);
+ return static_cast<double>(now.tv_sec) + static_cast<double>(now.tv_usec / 1000000.0);
+}
+
+}
diff --git a/WebCore/platform/gtk/SystemTimeLinux.cpp b/WebCore/platform/gtk/SystemTimeLinux.cpp
new file mode 100644
index 0000000..45caddd
--- /dev/null
+++ b/WebCore/platform/gtk/SystemTimeLinux.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SystemTime.h"
+
+#include <sys/time.h>
+
+namespace WebCore {
+
+double currentTime()
+{
+ struct timeval aTimeval;
+ struct timezone aTimezone;
+
+ gettimeofday( &aTimeval, &aTimezone );
+ return (double)aTimeval.tv_sec + (double)(aTimeval.tv_usec / 1000000.0 );
+}
+
+}
diff --git a/WebCore/platform/gtk/TemporaryLinkStubs.cpp b/WebCore/platform/gtk/TemporaryLinkStubs.cpp
new file mode 100644
index 0000000..5093794
--- /dev/null
+++ b/WebCore/platform/gtk/TemporaryLinkStubs.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "AXObjectCache.h"
+#include "DNS.h"
+#include "Editor.h"
+#include "FrameView.h"
+#include "FTPDirectoryDocument.h"
+#include "NotImplemented.h"
+#include "PluginView.h"
+#include <float.h>
+
+using namespace WebCore;
+
+// This function loads resources from WebKit
+// This does not belong here and I'm not sure where
+// it should go
+// I don't know what the plans or design is
+// for none code resources
+Vector<char> loadResourceIntoArray(const char* resourceName)
+{
+ Vector<char> resource;
+ //if (strcmp(resourceName,"missingImage") == 0) {
+ //}
+ return resource;
+}
+
+
+/********************************************************/
+/* Completely empty stubs (mostly to allow DRT to run): */
+/********************************************************/
+
+void PluginView::invalidateRegion(NPRegion) { notImplemented(); }
+
+Color WebCore::focusRingColor() { return Color(); }
+
+namespace WebCore {
+void getSupportedKeySizes(Vector<String>&) { notImplemented(); }
+String signedPublicKeyAndChallengeString(unsigned keySizeIndex, const String &challengeString, const KURL &url) { return String(); }
+float userIdleTime() { notImplemented(); return FLT_MAX; } // return an arbitrarily high userIdleTime so that releasing pages from the page cache isn't postponed
+
+}
diff --git a/WebCore/platform/gtk/WheelEventGtk.cpp b/WebCore/platform/gtk/WheelEventGtk.cpp
new file mode 100644
index 0000000..fbe31f7
--- /dev/null
+++ b/WebCore/platform/gtk/WheelEventGtk.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PlatformWheelEvent.h"
+
+#include <gdk/gdk.h>
+#include <gtk/gtkversion.h>
+
+namespace WebCore {
+
+// Keep this in sync with the other platform event constructors
+PlatformWheelEvent::PlatformWheelEvent(GdkEventScroll* event)
+{
+ static const float delta = 1;
+
+ m_deltaX = 0;
+ m_deltaY = 0;
+
+ // Docs say an upwards scroll (away from the user) has a positive delta
+ switch (event->direction) {
+ case GDK_SCROLL_UP:
+ m_deltaY = delta;
+ break;
+ case GDK_SCROLL_DOWN:
+ m_deltaY = -delta;
+ break;
+ case GDK_SCROLL_LEFT:
+ m_deltaX = -delta;
+ break;
+ case GDK_SCROLL_RIGHT:
+ m_deltaX = delta;
+ break;
+ }
+
+ m_position = IntPoint((int)event->x, (int)event->y);
+ m_globalPosition = IntPoint((int)event->x_root, (int)event->y_root);
+ m_granularity = ScrollByLineWheelEvent;
+ m_isAccepted = false;
+ m_shiftKey = event->state & GDK_SHIFT_MASK;
+ m_ctrlKey = event->state & GDK_CONTROL_MASK;
+ m_altKey = event->state & GDK_MOD1_MASK;
+#if GTK_CHECK_VERSION(2,10,0)
+ m_metaKey = event->state & GDK_META_MASK;
+#else
+ // GDK_MOD2_MASK doesn't always mean meta so we can't use it
+ m_metaKey = false;
+#endif
+
+ // FIXME: retrieve the user setting for the number of lines to scroll on each wheel event
+ m_deltaX *= horizontalLineMultiplier();
+ m_deltaY *= verticalLineMultiplier();
+}
+
+}
diff --git a/WebCore/platform/gtk/WidgetGtk.cpp b/WebCore/platform/gtk/WidgetGtk.cpp
new file mode 100644
index 0000000..82fed74
--- /dev/null
+++ b/WebCore/platform/gtk/WidgetGtk.cpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Widget.h"
+
+#include "Cursor.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "HostWindow.h"
+#include "IntRect.h"
+#include "NotImplemented.h"
+#include "RenderObject.h"
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+namespace WebCore {
+
+class WidgetPrivate {
+public:
+ GdkCursor* cursor;
+};
+
+Widget::Widget(PlatformWidget widget)
+ : m_data(new WidgetPrivate)
+{
+ init(widget);
+ m_data->cursor = 0;
+}
+
+Widget::~Widget()
+{
+ ASSERT(!parent());
+ releasePlatformWidget();
+ delete m_data;
+}
+
+void Widget::setFocus()
+{
+ gtk_widget_grab_focus(platformWidget() ? platformWidget() : GTK_WIDGET(root()->hostWindow()->platformWindow()));
+}
+
+Cursor Widget::cursor()
+{
+ return Cursor(m_data->cursor);
+}
+
+static GdkDrawable* gdkDrawable(PlatformWidget widget)
+{
+ return widget ? widget->window : 0;
+}
+
+void Widget::setCursor(const Cursor& cursor)
+{
+ GdkCursor* pcur = cursor.impl();
+
+ // http://bugs.webkit.org/show_bug.cgi?id=16388
+ // [GTK] Widget::setCursor() gets called frequently
+ //
+ // gdk_window_set_cursor() in certain GDK backends seems to be an
+ // expensive operation, so avoid it if possible.
+
+ if (pcur == m_data->cursor)
+ return;
+
+ gdk_window_set_cursor(gdkDrawable(platformWidget()) ? GDK_WINDOW(gdkDrawable(platformWidget())) : GTK_WIDGET(root()->hostWindow()->platformWindow())->window, pcur);
+ m_data->cursor = pcur;
+}
+
+void Widget::show()
+{
+ if (!platformWidget())
+ return;
+ gtk_widget_show(platformWidget());
+}
+
+void Widget::hide()
+{
+ if (!platformWidget())
+ return;
+ gtk_widget_hide(platformWidget());
+}
+
+/*
+ * Strategy to painting a Widget:
+ * 1.) do not paint if there is no GtkWidget set
+ * 2.) We assume that GTK_NO_WINDOW is set and that frameRectsChanged positioned
+ * the widget correctly. ATM we do not honor the GraphicsContext translation.
+ */
+void Widget::paint(GraphicsContext* context, const IntRect&)
+{
+ if (!platformWidget())
+ return;
+
+ if (!context->gdkExposeEvent())
+ return;
+
+ GtkWidget* widget = platformWidget();
+ ASSERT(GTK_WIDGET_NO_WINDOW(widget));
+
+ GdkEvent* event = gdk_event_new(GDK_EXPOSE);
+ event->expose = *context->gdkExposeEvent();
+ event->expose.region = gtk_widget_region_intersect(widget, event->expose.region);
+
+ /*
+ * This will be unref'ed by gdk_event_free.
+ */
+ g_object_ref(event->expose.window);
+
+ /*
+ * If we are going to paint do the translation and GtkAllocation manipulation.
+ */
+ if (!gdk_region_empty(event->expose.region)) {
+ gdk_region_get_clipbox(event->expose.region, &event->expose.area);
+ gtk_widget_send_expose(widget, event);
+ }
+
+ gdk_event_free(event);
+}
+
+void Widget::setIsSelected(bool)
+{
+ notImplemented();
+}
+
+IntRect Widget::frameRect() const
+{
+ return m_frame;
+}
+
+void Widget::setFrameRect(const IntRect& rect)
+{
+ m_frame = rect;
+}
+
+void Widget::releasePlatformWidget()
+{
+ if (!platformWidget())
+ return;
+ g_object_unref(platformWidget());
+}
+
+void Widget::retainPlatformWidget()
+{
+ if (!platformWidget())
+ return;
+#if GLIB_CHECK_VERSION(2,10,0)
+ g_object_ref_sink(platformWidget());
+#else
+ g_object_ref(platformWidget());
+ gtk_object_sink(GTK_OBJECT(platformWidget()));
+#endif
+}
+
+}
diff --git a/WebCore/platform/gtk/gtk2drawing.c b/WebCore/platform/gtk/gtk2drawing.c
new file mode 100644
index 0000000..83b4cb4
--- /dev/null
+++ b/WebCore/platform/gtk/gtk2drawing.c
@@ -0,0 +1,3311 @@
+/* -*- 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) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brian Ryner <bryner@brianryner.com> (Original Author)
+ * Pierre Chanial <p_ch@verizon.net>
+ * Michael Ventnor <m.ventnor@gmail.com>
+ * Alp Toker <alp@nuanti.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 ***** */
+
+/*
+ * This file contains painting functions for each of the gtk2 widgets.
+ * Adapted from the gtkdrawing.c, and gtk+2.0 source.
+ */
+
+#include <gtk/gtk.h>
+#include <gdk/gdkprivate.h>
+#include <string.h>
+#include "gtkdrawing.h"
+
+#include <math.h>
+
+#define XTHICKNESS(style) (style->xthickness)
+#define YTHICKNESS(style) (style->ythickness)
+#define WINDOW_IS_MAPPED(window) ((window) && GDK_IS_WINDOW(window) && gdk_window_is_visible(window))
+
+static GtkWidget* gProtoWindow;
+static GtkWidget* gButtonWidget;
+static GtkWidget* gToggleButtonWidget;
+static GtkWidget* gButtonArrowWidget;
+static GtkWidget* gCheckboxWidget;
+static GtkWidget* gRadiobuttonWidget;
+static GtkWidget* gHorizScrollbarWidget;
+static GtkWidget* gVertScrollbarWidget;
+static GtkWidget* gSpinWidget;
+static GtkWidget* gHScaleWidget;
+static GtkWidget* gVScaleWidget;
+static GtkWidget* gEntryWidget;
+static GtkWidget* gComboBoxWidget;
+static GtkWidget* gComboBoxButtonWidget;
+static GtkWidget* gComboBoxArrowWidget;
+static GtkWidget* gComboBoxSeparatorWidget;
+static GtkWidget* gComboBoxEntryWidget;
+static GtkWidget* gComboBoxEntryTextareaWidget;
+static GtkWidget* gComboBoxEntryButtonWidget;
+static GtkWidget* gComboBoxEntryArrowWidget;
+static GtkWidget* gHandleBoxWidget;
+static GtkWidget* gToolbarWidget;
+static GtkWidget* gFrameWidget;
+static GtkWidget* gStatusbarWidget;
+static GtkWidget* gProgressWidget;
+static GtkWidget* gTabWidget;
+static GtkWidget* gTooltipWidget;
+static GtkWidget* gMenuBarWidget;
+static GtkWidget* gMenuBarItemWidget;
+static GtkWidget* gMenuPopupWidget;
+static GtkWidget* gMenuItemWidget;
+static GtkWidget* gImageMenuItemWidget;
+static GtkWidget* gCheckMenuItemWidget;
+static GtkWidget* gTreeViewWidget;
+static GtkWidget* gMiddleTreeViewColumn;
+static GtkWidget* gTreeHeaderCellWidget;
+static GtkWidget* gTreeHeaderSortArrowWidget;
+static GtkWidget* gExpanderWidget;
+static GtkWidget* gToolbarSeparatorWidget;
+static GtkWidget* gMenuSeparatorWidget;
+static GtkWidget* gHPanedWidget;
+static GtkWidget* gVPanedWidget;
+static GtkWidget* gScrolledWindowWidget;
+
+static style_prop_t style_prop_func;
+static gboolean have_arrow_scaling;
+static gboolean have_2_10;
+static gboolean is_initialized;
+
+/* Because we have such an unconventional way of drawing widgets, signal to the GTK theme engine
+ that they are drawing for Mozilla instead of a conventional GTK app so they can do any specific
+ things they may want to do. */
+static void
+moz_gtk_set_widget_name(GtkWidget* widget)
+{
+ gtk_widget_set_name(widget, "MozillaGtkWidget");
+}
+
+gint
+moz_gtk_enable_style_props(style_prop_t styleGetProp)
+{
+ style_prop_func = styleGetProp;
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_window_widget()
+{
+ if (!gProtoWindow) {
+ gProtoWindow = gtk_window_new(GTK_WINDOW_POPUP);
+ gtk_widget_realize(gProtoWindow);
+ moz_gtk_set_widget_name(gProtoWindow);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+setup_widget_prototype(GtkWidget* widget)
+{
+ static GtkWidget* protoLayout;
+ ensure_window_widget();
+ if (!protoLayout) {
+ protoLayout = gtk_fixed_new();
+ gtk_container_add(GTK_CONTAINER(gProtoWindow), protoLayout);
+ }
+
+ gtk_container_add(GTK_CONTAINER(protoLayout), widget);
+ gtk_widget_realize(widget);
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", TRUE);
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_button_widget()
+{
+ if (!gButtonWidget) {
+ gButtonWidget = gtk_button_new_with_label("M");
+ setup_widget_prototype(gButtonWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_hpaned_widget()
+{
+ if (!gHPanedWidget) {
+ gHPanedWidget = gtk_hpaned_new();
+ setup_widget_prototype(gHPanedWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_vpaned_widget()
+{
+ if (!gVPanedWidget) {
+ gVPanedWidget = gtk_vpaned_new();
+ setup_widget_prototype(gVPanedWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_toggle_button_widget()
+{
+ if (!gToggleButtonWidget) {
+ gToggleButtonWidget = gtk_toggle_button_new();
+ setup_widget_prototype(gToggleButtonWidget);
+ /* toggle button must be set active to get the right style on hover. */
+ GTK_TOGGLE_BUTTON(gToggleButtonWidget)->active = TRUE;
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_button_arrow_widget()
+{
+ if (!gButtonArrowWidget) {
+ ensure_toggle_button_widget();
+
+ gButtonArrowWidget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
+ gtk_container_add(GTK_CONTAINER(gToggleButtonWidget), gButtonArrowWidget);
+ gtk_widget_realize(gButtonArrowWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_checkbox_widget()
+{
+ if (!gCheckboxWidget) {
+ gCheckboxWidget = gtk_check_button_new_with_label("M");
+ setup_widget_prototype(gCheckboxWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_radiobutton_widget()
+{
+ if (!gRadiobuttonWidget) {
+ gRadiobuttonWidget = gtk_radio_button_new_with_label(NULL, "M");
+ setup_widget_prototype(gRadiobuttonWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_scrollbar_widget()
+{
+ if (!gVertScrollbarWidget) {
+ gVertScrollbarWidget = gtk_vscrollbar_new(NULL);
+ setup_widget_prototype(gVertScrollbarWidget);
+ }
+ if (!gHorizScrollbarWidget) {
+ gHorizScrollbarWidget = gtk_hscrollbar_new(NULL);
+ setup_widget_prototype(gHorizScrollbarWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_spin_widget()
+{
+ if (!gSpinWidget) {
+ gSpinWidget = gtk_spin_button_new(NULL, 1, 0);
+ setup_widget_prototype(gSpinWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_scale_widget()
+{
+ if (!gHScaleWidget) {
+ gHScaleWidget = gtk_hscale_new(NULL);
+ setup_widget_prototype(gHScaleWidget);
+ }
+ if (!gVScaleWidget) {
+ gVScaleWidget = gtk_vscale_new(NULL);
+ setup_widget_prototype(gVScaleWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_entry_widget()
+{
+ if (!gEntryWidget) {
+ gEntryWidget = gtk_entry_new();
+ setup_widget_prototype(gEntryWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+/* We need to have pointers to the inner widgets (button, separator, arrow)
+ * of the ComboBox to get the correct rendering from theme engines which
+ * special cases their look. Since the inner layout can change, we ask GTK
+ * to NULL our pointers when they are about to become invalid because the
+ * corresponding widgets don't exist anymore. It's the role of
+ * g_object_add_weak_pointer().
+ * Note that if we don't find the inner widgets (which shouldn't happen), we
+ * fallback to use generic "non-inner" widgets, and they don't need that kind
+ * of weak pointer since they are explicit children of gProtoWindow and as
+ * such GTK holds a strong reference to them. */
+static void
+moz_gtk_get_combo_box_inner_button(GtkWidget *widget, gpointer client_data)
+{
+ if (GTK_IS_TOGGLE_BUTTON(widget)) {
+ gComboBoxButtonWidget = widget;
+ g_object_add_weak_pointer(G_OBJECT(widget),
+ (gpointer) &gComboBoxButtonWidget);
+ gtk_widget_realize(widget);
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", TRUE);
+ }
+}
+
+static void
+moz_gtk_get_combo_box_button_inner_widgets(GtkWidget *widget,
+ gpointer client_data)
+{
+ if (GTK_IS_SEPARATOR(widget)) {
+ gComboBoxSeparatorWidget = widget;
+ g_object_add_weak_pointer(G_OBJECT(widget),
+ (gpointer) &gComboBoxSeparatorWidget);
+ } else if (GTK_IS_ARROW(widget)) {
+ gComboBoxArrowWidget = widget;
+ g_object_add_weak_pointer(G_OBJECT(widget),
+ (gpointer) &gComboBoxArrowWidget);
+ } else
+ return;
+ gtk_widget_realize(widget);
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", TRUE);
+}
+
+static gint
+ensure_combo_box_widgets()
+{
+ GtkWidget* buttonChild;
+
+ if (gComboBoxButtonWidget && gComboBoxArrowWidget)
+ return MOZ_GTK_SUCCESS;
+
+ /* Create a ComboBox if needed */
+ if (!gComboBoxWidget) {
+ gComboBoxWidget = gtk_combo_box_new();
+ setup_widget_prototype(gComboBoxWidget);
+ }
+
+ /* Get its inner Button */
+ gtk_container_forall(GTK_CONTAINER(gComboBoxWidget),
+ moz_gtk_get_combo_box_inner_button,
+ NULL);
+
+ if (gComboBoxButtonWidget) {
+ /* Get the widgets inside the Button */
+ buttonChild = GTK_BIN(gComboBoxButtonWidget)->child;
+ if (GTK_IS_HBOX(buttonChild)) {
+ /* appears-as-list = FALSE, cell-view = TRUE; the button
+ * contains an hbox. This hbox is there because the ComboBox
+ * needs to place a cell renderer, a separator, and an arrow in
+ * the button when appears-as-list is FALSE. */
+ gtk_container_forall(GTK_CONTAINER(buttonChild),
+ moz_gtk_get_combo_box_button_inner_widgets,
+ NULL);
+ } else if(GTK_IS_ARROW(buttonChild)) {
+ /* appears-as-list = TRUE, or cell-view = FALSE;
+ * the button only contains an arrow */
+ gComboBoxArrowWidget = buttonChild;
+ g_object_add_weak_pointer(G_OBJECT(buttonChild), (gpointer)
+ &gComboBoxArrowWidget);
+ gtk_widget_realize(gComboBoxArrowWidget);
+ g_object_set_data(G_OBJECT(gComboBoxArrowWidget),
+ "transparent-bg-hint", TRUE);
+ }
+ } else {
+ /* Shouldn't be reached with current internal gtk implementation; we
+ * use a generic toggle button as last resort fallback to avoid
+ * crashing. */
+ ensure_toggle_button_widget();
+ gComboBoxButtonWidget = gToggleButtonWidget;
+ }
+
+ if (!gComboBoxArrowWidget) {
+ /* Shouldn't be reached with current internal gtk implementation;
+ * we gButtonArrowWidget as last resort fallback to avoid
+ * crashing. */
+ ensure_button_arrow_widget();
+ gComboBoxArrowWidget = gButtonArrowWidget;
+ }
+
+ /* We don't test the validity of gComboBoxSeparatorWidget since there
+ * is none when "appears-as-list" = TRUE or "cell-view" = FALSE; if it
+ * is invalid we just won't paint it. */
+
+ return MOZ_GTK_SUCCESS;
+}
+
+/* We need to have pointers to the inner widgets (entry, button, arrow) of
+ * the ComboBoxEntry to get the correct rendering from theme engines which
+ * special cases their look. Since the inner layout can change, we ask GTK
+ * to NULL our pointers when they are about to become invalid because the
+ * corresponding widgets don't exist anymore. It's the role of
+ * g_object_add_weak_pointer().
+ * Note that if we don't find the inner widgets (which shouldn't happen), we
+ * fallback to use generic "non-inner" widgets, and they don't need that kind
+ * of weak pointer since they are explicit children of gProtoWindow and as
+ * such GTK holds a strong reference to them. */
+static void
+moz_gtk_get_combo_box_entry_inner_widgets(GtkWidget *widget,
+ gpointer client_data)
+{
+ if (GTK_IS_TOGGLE_BUTTON(widget)) {
+ gComboBoxEntryButtonWidget = widget;
+ g_object_add_weak_pointer(G_OBJECT(widget),
+ (gpointer) &gComboBoxEntryButtonWidget);
+ } else if (GTK_IS_ENTRY(widget)) {
+ gComboBoxEntryTextareaWidget = widget;
+ g_object_add_weak_pointer(G_OBJECT(widget),
+ (gpointer) &gComboBoxEntryTextareaWidget);
+ } else
+ return;
+ gtk_widget_realize(widget);
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", TRUE);
+}
+
+static void
+moz_gtk_get_combo_box_entry_arrow(GtkWidget *widget, gpointer client_data)
+{
+ if (GTK_IS_ARROW(widget)) {
+ gComboBoxEntryArrowWidget = widget;
+ g_object_add_weak_pointer(G_OBJECT(widget),
+ (gpointer) &gComboBoxEntryArrowWidget);
+ gtk_widget_realize(widget);
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", TRUE);
+ }
+}
+
+static gint
+ensure_combo_box_entry_widgets()
+{
+ GtkWidget* buttonChild;
+
+ if (gComboBoxEntryTextareaWidget &&
+ gComboBoxEntryButtonWidget &&
+ gComboBoxEntryArrowWidget)
+ return MOZ_GTK_SUCCESS;
+
+ /* Create a ComboBoxEntry if needed */
+ if (!gComboBoxEntryWidget) {
+ gComboBoxEntryWidget = gtk_combo_box_entry_new();
+ setup_widget_prototype(gComboBoxEntryWidget);
+ }
+
+ /* Get its inner Entry and Button */
+ gtk_container_forall(GTK_CONTAINER(gComboBoxEntryWidget),
+ moz_gtk_get_combo_box_entry_inner_widgets,
+ NULL);
+
+ if (!gComboBoxEntryTextareaWidget) {
+ ensure_entry_widget();
+ gComboBoxEntryTextareaWidget = gEntryWidget;
+ }
+
+ if (gComboBoxEntryButtonWidget) {
+ /* Get the Arrow inside the Button */
+ buttonChild = GTK_BIN(gComboBoxEntryButtonWidget)->child;
+ if (GTK_IS_HBOX(buttonChild)) {
+ /* appears-as-list = FALSE, cell-view = TRUE; the button
+ * contains an hbox. This hbox is there because ComboBoxEntry
+ * inherits from ComboBox which needs to place a cell renderer,
+ * a separator, and an arrow in the button when appears-as-list
+ * is FALSE. Here the hbox should only contain an arrow, since
+ * a ComboBoxEntry doesn't need all those widgets in the
+ * button. */
+ gtk_container_forall(GTK_CONTAINER(buttonChild),
+ moz_gtk_get_combo_box_entry_arrow,
+ NULL);
+ } else if(GTK_IS_ARROW(buttonChild)) {
+ /* appears-as-list = TRUE, or cell-view = FALSE;
+ * the button only contains an arrow */
+ gComboBoxEntryArrowWidget = buttonChild;
+ g_object_add_weak_pointer(G_OBJECT(buttonChild), (gpointer)
+ &gComboBoxEntryArrowWidget);
+ gtk_widget_realize(gComboBoxEntryArrowWidget);
+ g_object_set_data(G_OBJECT(gComboBoxEntryArrowWidget),
+ "transparent-bg-hint", TRUE);
+ }
+ } else {
+ /* Shouldn't be reached with current internal gtk implementation;
+ * we use a generic toggle button as last resort fallback to avoid
+ * crashing. */
+ ensure_toggle_button_widget();
+ gComboBoxEntryButtonWidget = gToggleButtonWidget;
+ }
+
+ if (!gComboBoxEntryArrowWidget) {
+ /* Shouldn't be reached with current internal gtk implementation;
+ * we gButtonArrowWidget as last resort fallback to avoid
+ * crashing. */
+ ensure_button_arrow_widget();
+ gComboBoxEntryArrowWidget = gButtonArrowWidget;
+ }
+
+ return MOZ_GTK_SUCCESS;
+}
+
+
+static gint
+ensure_handlebox_widget()
+{
+ if (!gHandleBoxWidget) {
+ gHandleBoxWidget = gtk_handle_box_new();
+ setup_widget_prototype(gHandleBoxWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_toolbar_widget()
+{
+ if (!gToolbarWidget) {
+ ensure_handlebox_widget();
+ gToolbarWidget = gtk_toolbar_new();
+ gtk_container_add(GTK_CONTAINER(gHandleBoxWidget), gToolbarWidget);
+ gtk_widget_realize(gToolbarWidget);
+ g_object_set_data(G_OBJECT(gToolbarWidget), "transparent-bg-hint", TRUE);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_toolbar_separator_widget()
+{
+ if (!gToolbarSeparatorWidget) {
+ ensure_toolbar_widget();
+ gToolbarSeparatorWidget = GTK_WIDGET(gtk_separator_tool_item_new());
+ setup_widget_prototype(gToolbarSeparatorWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_tooltip_widget()
+{
+ if (!gTooltipWidget) {
+ gTooltipWidget = gtk_window_new(GTK_WINDOW_POPUP);
+ gtk_widget_realize(gTooltipWidget);
+ moz_gtk_set_widget_name(gTooltipWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_tab_widget()
+{
+ if (!gTabWidget) {
+ gTabWidget = gtk_notebook_new();
+ setup_widget_prototype(gTabWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_progress_widget()
+{
+ if (!gProgressWidget) {
+ gProgressWidget = gtk_progress_bar_new();
+ setup_widget_prototype(gProgressWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_statusbar_widget()
+{
+ if (!gStatusbarWidget) {
+ gStatusbarWidget = gtk_statusbar_new();
+ setup_widget_prototype(gStatusbarWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_frame_widget()
+{
+ if (!gFrameWidget) {
+ ensure_statusbar_widget();
+ gFrameWidget = gtk_frame_new(NULL);
+ gtk_container_add(GTK_CONTAINER(gStatusbarWidget), gFrameWidget);
+ gtk_widget_realize(gFrameWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_menu_bar_widget()
+{
+ if (!gMenuBarWidget) {
+ gMenuBarWidget = gtk_menu_bar_new();
+ setup_widget_prototype(gMenuBarWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_menu_bar_item_widget()
+{
+ if (!gMenuBarItemWidget) {
+ ensure_menu_bar_widget();
+ gMenuBarItemWidget = gtk_menu_item_new();
+ gtk_menu_shell_append(GTK_MENU_SHELL(gMenuBarWidget),
+ gMenuBarItemWidget);
+ gtk_widget_realize(gMenuBarItemWidget);
+ g_object_set_data(G_OBJECT(gMenuBarItemWidget),
+ "transparent-bg-hint", TRUE);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_menu_popup_widget()
+{
+ if (!gMenuPopupWidget) {
+ ensure_menu_bar_item_widget();
+ gMenuPopupWidget = gtk_menu_new();
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(gMenuBarItemWidget),
+ gMenuPopupWidget);
+ gtk_widget_realize(gMenuPopupWidget);
+ g_object_set_data(G_OBJECT(gMenuPopupWidget),
+ "transparent-bg-hint", TRUE);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_menu_item_widget()
+{
+ if (!gMenuItemWidget) {
+ ensure_menu_popup_widget();
+ gMenuItemWidget = gtk_menu_item_new_with_label("M");
+ gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
+ gMenuItemWidget);
+ gtk_widget_realize(gMenuItemWidget);
+ g_object_set_data(G_OBJECT(gMenuItemWidget),
+ "transparent-bg-hint", TRUE);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_image_menu_item_widget()
+{
+ if (!gImageMenuItemWidget) {
+ ensure_menu_popup_widget();
+ gImageMenuItemWidget = gtk_image_menu_item_new();
+ gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
+ gImageMenuItemWidget);
+ gtk_widget_realize(gImageMenuItemWidget);
+ g_object_set_data(G_OBJECT(gImageMenuItemWidget),
+ "transparent-bg-hint", TRUE);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_menu_separator_widget()
+{
+ if (!gMenuSeparatorWidget) {
+ ensure_menu_popup_widget();
+ gMenuSeparatorWidget = gtk_separator_menu_item_new();
+ gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
+ gMenuSeparatorWidget);
+ gtk_widget_realize(gMenuSeparatorWidget);
+ g_object_set_data(G_OBJECT(gMenuSeparatorWidget),
+ "transparent-bg-hint", TRUE);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_check_menu_item_widget()
+{
+ if (!gCheckMenuItemWidget) {
+ ensure_menu_popup_widget();
+ gCheckMenuItemWidget = gtk_check_menu_item_new_with_label("M");
+ gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
+ gCheckMenuItemWidget);
+ gtk_widget_realize(gCheckMenuItemWidget);
+ g_object_set_data(G_OBJECT(gCheckMenuItemWidget),
+ "transparent-bg-hint", TRUE);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_tree_view_widget()
+{
+ if (!gTreeViewWidget) {
+ gTreeViewWidget = gtk_tree_view_new();
+ setup_widget_prototype(gTreeViewWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_tree_header_cell_widget()
+{
+ if(!gTreeHeaderCellWidget) {
+ /*
+ * Some GTK engines paint the first and last cell
+ * of a TreeView header with a highlight.
+ * Since we do not know where our widget will be relative
+ * to the other buttons in the TreeView header, we must
+ * paint it as a button that is between two others,
+ * thus ensuring it is neither the first or last button
+ * in the header.
+ * GTK doesn't give us a way to do this explicitly,
+ * so we must paint with a button that is between two
+ * others.
+ */
+
+ GtkTreeViewColumn* firstTreeViewColumn;
+ GtkTreeViewColumn* lastTreeViewColumn;
+
+ ensure_tree_view_widget();
+
+ /* Create and append our three columns */
+ firstTreeViewColumn = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title(firstTreeViewColumn, "M");
+ gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), firstTreeViewColumn);
+
+ gMiddleTreeViewColumn = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title(GTK_TREE_VIEW_COLUMN(gMiddleTreeViewColumn), "M");
+ gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget),
+ GTK_TREE_VIEW_COLUMN(gMiddleTreeViewColumn));
+
+ lastTreeViewColumn = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title(lastTreeViewColumn, "M");
+ gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), lastTreeViewColumn);
+
+ /* Use the middle column's header for our button */
+ gTreeHeaderCellWidget = GTK_TREE_VIEW_COLUMN(gMiddleTreeViewColumn)->button;
+ gTreeHeaderSortArrowWidget = GTK_TREE_VIEW_COLUMN(gMiddleTreeViewColumn)->arrow;
+ g_object_set_data(G_OBJECT(gTreeHeaderCellWidget),
+ "transparent-bg-hint", TRUE);
+ g_object_set_data(G_OBJECT(gTreeHeaderSortArrowWidget),
+ "transparent-bg-hint", TRUE);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_expander_widget()
+{
+ if (!gExpanderWidget) {
+ gExpanderWidget = gtk_expander_new("M");
+ setup_widget_prototype(gExpanderWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+ensure_scrolled_window_widget()
+{
+ if (!gScrolledWindowWidget) {
+ gScrolledWindowWidget = gtk_scrolled_window_new(NULL, NULL);
+ setup_widget_prototype(gScrolledWindowWidget);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+static GtkStateType
+ConvertGtkState(GtkWidgetState* state)
+{
+ if (state->disabled)
+ return GTK_STATE_INSENSITIVE;
+ else if (state->depressed)
+ return (state->inHover ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
+ else if (state->inHover)
+ return (state->active ? GTK_STATE_ACTIVE : GTK_STATE_PRELIGHT);
+ else
+ return GTK_STATE_NORMAL;
+}
+
+static gint
+TSOffsetStyleGCArray(GdkGC** gcs, gint xorigin, gint yorigin)
+{
+ int i;
+ /* there are 5 gc's in each array, for each of the widget states */
+ for (i = 0; i < 5; ++i)
+ gdk_gc_set_ts_origin(gcs[i], xorigin, yorigin);
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+TSOffsetStyleGCs(GtkStyle* style, gint xorigin, gint yorigin)
+{
+ TSOffsetStyleGCArray(style->fg_gc, xorigin, yorigin);
+ TSOffsetStyleGCArray(style->bg_gc, xorigin, yorigin);
+ TSOffsetStyleGCArray(style->light_gc, xorigin, yorigin);
+ TSOffsetStyleGCArray(style->dark_gc, xorigin, yorigin);
+ TSOffsetStyleGCArray(style->mid_gc, xorigin, yorigin);
+ TSOffsetStyleGCArray(style->text_gc, xorigin, yorigin);
+ TSOffsetStyleGCArray(style->base_gc, xorigin, yorigin);
+ gdk_gc_set_ts_origin(style->black_gc, xorigin, yorigin);
+ gdk_gc_set_ts_origin(style->white_gc, xorigin, yorigin);
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ GtkReliefStyle relief, GtkWidget* widget,
+ GtkTextDirection direction)
+{
+ GtkShadowType shadow_type;
+ GtkStyle* style = widget->style;
+ GtkStateType button_state = ConvertGtkState(state);
+ gint x = rect->x, y=rect->y, width=rect->width, height=rect->height;
+
+ gboolean interior_focus;
+ gint focus_width, focus_pad;
+
+ moz_gtk_widget_get_focus(widget, &interior_focus, &focus_width, &focus_pad);
+
+ if (WINDOW_IS_MAPPED(drawable)) {
+ gdk_window_set_back_pixmap(drawable, NULL, TRUE);
+ gdk_window_clear_area(drawable, cliprect->x, cliprect->y,
+ cliprect->width, cliprect->height);
+ }
+
+ gtk_widget_set_state(widget, button_state);
+ gtk_widget_set_direction(widget, direction);
+
+ if (state->isDefault)
+ GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_DEFAULT);
+
+ GTK_BUTTON(widget)->relief = relief;
+
+ /* Some theme engines love to cause us pain in that gtk_paint_focus is a
+ no-op on buttons and button-like widgets. They only listen to this flag. */
+ if (state->focused && !state->disabled)
+ GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
+
+ if (!interior_focus && state->focused) {
+ x += focus_width + focus_pad;
+ y += focus_width + focus_pad;
+ width -= 2 * (focus_width + focus_pad);
+ height -= 2 * (focus_width + focus_pad);
+ }
+
+ shadow_type = button_state == GTK_STATE_ACTIVE ||
+ state->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
+
+ if (state->isDefault && relief == GTK_RELIEF_NORMAL) {
+ gtk_paint_box(style, drawable, button_state, shadow_type, cliprect,
+ widget, "buttondefault", x, y, width, height);
+ }
+
+ if (relief != GTK_RELIEF_NONE || state->depressed ||
+ (button_state != GTK_STATE_NORMAL &&
+ button_state != GTK_STATE_INSENSITIVE)) {
+ TSOffsetStyleGCs(style, x, y);
+ /* the following line can trigger an assertion (Crux theme)
+ file ../../gdk/gdkwindow.c: line 1846 (gdk_window_clear_area):
+ assertion `GDK_IS_WINDOW (window)' failed */
+ gtk_paint_box(style, drawable, button_state, shadow_type, cliprect,
+ widget, "button", x, y, width, height);
+ }
+
+ if (state->focused) {
+ if (interior_focus) {
+ x += widget->style->xthickness + focus_pad;
+ y += widget->style->ythickness + focus_pad;
+ width -= 2 * (widget->style->xthickness + focus_pad);
+ height -= 2 * (widget->style->ythickness + focus_pad);
+ } else {
+ x -= focus_width + focus_pad;
+ y -= focus_width + focus_pad;
+ width += 2 * (focus_width + focus_pad);
+ height += 2 * (focus_width + focus_pad);
+ }
+
+ TSOffsetStyleGCs(style, x, y);
+ gtk_paint_focus(style, drawable, button_state, cliprect,
+ widget, "button", x, y, width, height);
+ }
+
+ GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_DEFAULT);
+ GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS);
+ return MOZ_GTK_SUCCESS;
+}
+
+gint
+moz_gtk_init()
+{
+ GtkWidgetClass *entry_class;
+
+ is_initialized = TRUE;
+ have_arrow_scaling = (gtk_major_version > 2 ||
+ (gtk_major_version == 2 && gtk_minor_version >= 12));
+
+ have_2_10 = (gtk_major_version > 2 ||
+ (gtk_major_version == 2 && gtk_minor_version >= 10));
+
+ /* Add style property to GtkEntry.
+ * Adding the style property to the normal GtkEntry class means that it
+ * will work without issues inside GtkComboBox and for Spinbuttons. */
+ entry_class = g_type_class_ref(GTK_TYPE_ENTRY);
+ gtk_widget_class_install_style_property(entry_class,
+ g_param_spec_boolean("honors-transparent-bg-hint",
+ "Transparent BG enabling flag",
+ "If TRUE, the theme is able to draw the GtkEntry on non-prefilled background.",
+ FALSE,
+ G_PARAM_READWRITE));
+
+ return MOZ_GTK_SUCCESS;
+}
+
+gint
+moz_gtk_checkbox_get_metrics(gint* indicator_size, gint* indicator_spacing)
+{
+ ensure_checkbox_widget();
+
+ gtk_widget_style_get (gCheckboxWidget,
+ "indicator_size", indicator_size,
+ "indicator_spacing", indicator_spacing,
+ NULL);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+gint
+moz_gtk_radio_get_metrics(gint* indicator_size, gint* indicator_spacing)
+{
+ ensure_radiobutton_widget();
+
+ gtk_widget_style_get (gRadiobuttonWidget,
+ "indicator_size", indicator_size,
+ "indicator_spacing", indicator_spacing,
+ NULL);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+gint
+moz_gtk_widget_get_focus(GtkWidget* widget, gboolean* interior_focus,
+ gint* focus_width, gint* focus_pad)
+{
+ gtk_widget_style_get (widget,
+ "interior-focus", interior_focus,
+ "focus-line-width", focus_width,
+ "focus-padding", focus_pad,
+ NULL);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+gint
+moz_gtk_splitter_get_metrics(gint orientation, gint* size)
+{
+ if (orientation == GTK_ORIENTATION_HORIZONTAL) {
+ ensure_hpaned_widget();
+ gtk_widget_style_get(gHPanedWidget, "handle_size", size, NULL);
+ } else {
+ ensure_vpaned_widget();
+ gtk_widget_style_get(gVPanedWidget, "handle_size", size, NULL);
+ }
+ return MOZ_GTK_SUCCESS;
+}
+
+gint
+moz_gtk_button_get_inner_border(GtkWidget* widget, GtkBorder* inner_border)
+{
+ static const GtkBorder default_inner_border = { 1, 1, 1, 1 };
+ GtkBorder *tmp_border = NULL;
+
+ if (have_2_10)
+ gtk_widget_style_get (widget, "inner-border", &tmp_border, NULL);
+
+ if (tmp_border) {
+ *inner_border = *tmp_border;
+ gtk_border_free(tmp_border);
+ }
+ else
+ *inner_border = default_inner_border;
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ gboolean selected, gboolean isradio,
+ GtkTextDirection direction)
+{
+ GtkStateType state_type = ConvertGtkState(state);
+ GtkShadowType shadow_type = (selected)?GTK_SHADOW_IN:GTK_SHADOW_OUT;
+ gint indicator_size, indicator_spacing;
+ gint x, y, width, height;
+ gint focus_x, focus_y, focus_width, focus_height;
+ GtkWidget *w;
+ GtkStyle *style;
+
+ if (isradio) {
+ moz_gtk_radio_get_metrics(&indicator_size, &indicator_spacing);
+ w = gRadiobuttonWidget;
+ } else {
+ moz_gtk_checkbox_get_metrics(&indicator_size, &indicator_spacing);
+ w = gCheckboxWidget;
+ }
+
+ /*
+ * vertically center in the box, since XUL sometimes ignores our
+ * GetMinimumWidgetSize in the vertical dimension
+ */
+ x = rect->x;
+ y = rect->y + (rect->height - indicator_size) / 2;
+ width = indicator_size;
+ height = indicator_size;
+
+ focus_x = x - indicator_spacing;
+ focus_y = y - indicator_spacing;
+ focus_width = width + 2 * indicator_spacing;
+ focus_height = height + 2 * indicator_spacing;
+
+ style = w->style;
+ TSOffsetStyleGCs(style, x, y);
+
+ gtk_widget_set_sensitive(w, !state->disabled);
+ gtk_widget_set_direction(w, direction);
+ GTK_TOGGLE_BUTTON(w)->active = selected;
+
+ if (isradio) {
+ gtk_paint_option(style, drawable, state_type, shadow_type, cliprect,
+ gRadiobuttonWidget, "radiobutton", x, y,
+ width, height);
+ if (state->focused) {
+ gtk_paint_focus(style, drawable, GTK_STATE_ACTIVE, cliprect,
+ gRadiobuttonWidget, "radiobutton", focus_x, focus_y,
+ focus_width, focus_height);
+ }
+ }
+ else {
+ gtk_paint_check(style, drawable, state_type, shadow_type, cliprect,
+ gCheckboxWidget, "checkbutton", x, y, width, height);
+ if (state->focused) {
+ gtk_paint_focus(style, drawable, GTK_STATE_ACTIVE, cliprect,
+ gCheckboxWidget, "checkbutton", focus_x, focus_y,
+ focus_width, focus_height);
+ }
+ }
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+calculate_button_inner_rect(GtkWidget* button, GdkRectangle* rect,
+ GdkRectangle* inner_rect,
+ GtkTextDirection direction,
+ gboolean ignore_focus)
+{
+ GtkBorder inner_border;
+ gboolean interior_focus;
+ gint focus_width, focus_pad;
+ GtkStyle* style;
+
+ style = button->style;
+
+ /* This mirrors gtkbutton's child positioning */
+ moz_gtk_button_get_inner_border(button, &inner_border);
+ moz_gtk_widget_get_focus(button, &interior_focus,
+ &focus_width, &focus_pad);
+
+ if (ignore_focus)
+ focus_width = focus_pad = 0;
+
+ inner_rect->x = rect->x + XTHICKNESS(style) + focus_width + focus_pad;
+ inner_rect->x += direction == GTK_TEXT_DIR_LTR ?
+ inner_border.left : inner_border.right;
+ inner_rect->y = rect->y + inner_border.top + YTHICKNESS(style) +
+ focus_width + focus_pad;
+ inner_rect->width = MAX(1, rect->width - inner_border.left -
+ inner_border.right - (XTHICKNESS(style) + focus_pad + focus_width) * 2);
+ inner_rect->height = MAX(1, rect->height - inner_border.top -
+ inner_border.bottom - (YTHICKNESS(style) + focus_pad + focus_width) * 2);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+
+static gint
+calculate_arrow_rect(GtkWidget* arrow, GdkRectangle* rect,
+ GdkRectangle* arrow_rect, GtkTextDirection direction)
+{
+ /* defined in gtkarrow.c */
+ gfloat arrow_scaling = 0.7;
+ gfloat xalign, xpad;
+ gint extent;
+ GtkMisc* misc = GTK_MISC(arrow);
+
+ if (have_arrow_scaling)
+ gtk_widget_style_get(arrow, "arrow_scaling", &arrow_scaling, NULL);
+
+ extent = MIN((rect->width - misc->xpad * 2),
+ (rect->height - misc->ypad * 2)) * arrow_scaling;
+
+ xalign = direction == GTK_TEXT_DIR_LTR ? misc->xalign : 1.0 - misc->xalign;
+ xpad = misc->xpad + (rect->width - extent) * xalign;
+
+ arrow_rect->x = direction == GTK_TEXT_DIR_LTR ?
+ floor(rect->x + xpad) : ceil(rect->x + xpad);
+ arrow_rect->y = floor(rect->y + misc->ypad +
+ ((rect->height - extent) * misc->yalign));
+
+ arrow_rect->width = arrow_rect->height = extent;
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_scrollbar_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ GtkScrollbarButtonFlags flags,
+ GtkTextDirection direction)
+{
+ GtkStateType state_type = ConvertGtkState(state);
+ GtkShadowType shadow_type = (state->active) ?
+ GTK_SHADOW_IN : GTK_SHADOW_OUT;
+ GdkRectangle arrow_rect;
+ GtkStyle* style;
+ GtkWidget *scrollbar;
+ GtkArrowType arrow_type;
+ gint arrow_displacement_x, arrow_displacement_y;
+ const char* detail = (flags & MOZ_GTK_STEPPER_VERTICAL) ?
+ "vscrollbar" : "hscrollbar";
+
+ ensure_scrollbar_widget();
+
+ if (flags & MOZ_GTK_STEPPER_VERTICAL)
+ scrollbar = gVertScrollbarWidget;
+ else
+ scrollbar = gHorizScrollbarWidget;
+
+ gtk_widget_set_direction(scrollbar, direction);
+
+ /* Some theme engines (i.e., ClearLooks) check the scrollbar's allocation
+ to determine where it should paint rounded corners on the buttons.
+ We need to trick them into drawing the buttons the way we want them. */
+
+ scrollbar->allocation.x = rect->x;
+ scrollbar->allocation.y = rect->y;
+ scrollbar->allocation.width = rect->width;
+ scrollbar->allocation.height = rect->height;
+
+ if (flags & MOZ_GTK_STEPPER_VERTICAL) {
+ scrollbar->allocation.height *= 5;
+ if (flags & MOZ_GTK_STEPPER_DOWN) {
+ arrow_type = GTK_ARROW_DOWN;
+ if (flags & MOZ_GTK_STEPPER_BOTTOM)
+ scrollbar->allocation.y -= 4 * rect->height;
+ else
+ scrollbar->allocation.y -= rect->height;
+
+ } else {
+ arrow_type = GTK_ARROW_UP;
+ if (flags & MOZ_GTK_STEPPER_BOTTOM)
+ scrollbar->allocation.y -= 3 * rect->height;
+ }
+ } else {
+ scrollbar->allocation.width *= 5;
+ if (flags & MOZ_GTK_STEPPER_DOWN) {
+ arrow_type = GTK_ARROW_RIGHT;
+ if (flags & MOZ_GTK_STEPPER_BOTTOM)
+ scrollbar->allocation.x -= 4 * rect->width;
+ else
+ scrollbar->allocation.x -= rect->width;
+ } else {
+ arrow_type = GTK_ARROW_LEFT;
+ if (flags & MOZ_GTK_STEPPER_BOTTOM)
+ scrollbar->allocation.x -= 3 * rect->width;
+ }
+ }
+
+ style = scrollbar->style;
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+
+ gtk_paint_box(style, drawable, state_type, shadow_type, cliprect,
+ scrollbar, detail, rect->x, rect->y,
+ rect->width, rect->height);
+
+ arrow_rect.width = rect->width / 2;
+ arrow_rect.height = rect->height / 2;
+ arrow_rect.x = rect->x + (rect->width - arrow_rect.width) / 2;
+ arrow_rect.y = rect->y + (rect->height - arrow_rect.height) / 2;
+
+ if (state_type == GTK_STATE_ACTIVE) {
+ gtk_widget_style_get(scrollbar,
+ "arrow-displacement-x", &arrow_displacement_x,
+ "arrow-displacement-y", &arrow_displacement_y,
+ NULL);
+
+ arrow_rect.x += arrow_displacement_x;
+ arrow_rect.y += arrow_displacement_y;
+ }
+
+ gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
+ scrollbar, detail, arrow_type, TRUE, arrow_rect.x,
+ arrow_rect.y, arrow_rect.width, arrow_rect.height);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_scrollbar_trough_paint(GtkThemeWidgetType widget,
+ GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ GtkTextDirection direction)
+{
+ GtkStyle* style;
+ GtkScrollbar *scrollbar;
+
+ ensure_scrollbar_widget();
+
+ if (widget == MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL)
+ scrollbar = GTK_SCROLLBAR(gHorizScrollbarWidget);
+ else
+ scrollbar = GTK_SCROLLBAR(gVertScrollbarWidget);
+
+ gtk_widget_set_direction(GTK_WIDGET(scrollbar), direction);
+
+ style = GTK_WIDGET(scrollbar)->style;
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+ gtk_style_apply_default_background(style, drawable, TRUE, GTK_STATE_ACTIVE,
+ cliprect, rect->x, rect->y,
+ rect->width, rect->height);
+
+ gtk_paint_box(style, drawable, GTK_STATE_ACTIVE, GTK_SHADOW_IN, cliprect,
+ GTK_WIDGET(scrollbar), "trough", rect->x, rect->y,
+ rect->width, rect->height);
+
+ if (state->focused) {
+ gtk_paint_focus(style, drawable, GTK_STATE_ACTIVE, cliprect,
+ GTK_WIDGET(scrollbar), "trough",
+ rect->x, rect->y, rect->width, rect->height);
+ }
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_scrollbar_thumb_paint(GtkThemeWidgetType widget,
+ GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ GtkTextDirection direction)
+{
+ GtkStateType state_type = (state->inHover || state->active) ?
+ GTK_STATE_PRELIGHT : GTK_STATE_NORMAL;
+ GtkShadowType shadow_type = GTK_SHADOW_OUT;
+ GtkStyle* style;
+ GtkScrollbar *scrollbar;
+ GtkAdjustment *adj;
+ gboolean activate_slider;
+
+ ensure_scrollbar_widget();
+
+ if (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL)
+ scrollbar = GTK_SCROLLBAR(gHorizScrollbarWidget);
+ else
+ scrollbar = GTK_SCROLLBAR(gVertScrollbarWidget);
+
+ gtk_widget_set_direction(GTK_WIDGET(scrollbar), direction);
+
+ /* Make sure to set the scrollbar range before painting so that
+ everything is drawn properly. At least the bluecurve (and
+ maybe other) themes don't draw the top or bottom black line
+ surrounding the scrollbar if the theme thinks that it's butted
+ up against the scrollbar arrows. Note the increases of the
+ clip rect below. */
+ /* Changing the cliprect is pretty bogus. This lets themes draw
+ outside the frame, which means we don't invalidate them
+ correctly. See bug 297508. But some themes do seem to need
+ it. So we modify the frame's overflow area to account for what
+ we're doing here; see nsNativeThemeGTK::GetWidgetOverflow. */
+ adj = gtk_range_get_adjustment(GTK_RANGE(scrollbar));
+
+ if (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) {
+ cliprect->x -= 1;
+ cliprect->width += 2;
+ adj->page_size = rect->width;
+ }
+ else {
+ cliprect->y -= 1;
+ cliprect->height += 2;
+ adj->page_size = rect->height;
+ }
+
+ adj->lower = 0;
+ adj->value = state->curpos;
+ adj->upper = state->maxpos;
+ gtk_adjustment_changed(adj);
+
+ style = GTK_WIDGET(scrollbar)->style;
+
+ gtk_widget_style_get(GTK_WIDGET(scrollbar), "activate-slider",
+ &activate_slider, NULL);
+
+ if (activate_slider && state->active) {
+ shadow_type = GTK_SHADOW_IN;
+ state_type = GTK_STATE_ACTIVE;
+ }
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+
+ gtk_paint_slider(style, drawable, state_type, shadow_type, cliprect,
+ GTK_WIDGET(scrollbar), "slider", rect->x, rect->y,
+ rect->width, rect->height,
+ (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) ?
+ GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_spin_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GtkTextDirection direction)
+{
+ GtkStyle* style;
+
+ ensure_spin_widget();
+ gtk_widget_set_direction(gSpinWidget, direction);
+ style = gSpinWidget->style;
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+ gtk_paint_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN, NULL,
+ gSpinWidget, "spinbutton",
+ rect->x, rect->y, rect->width, rect->height);
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_spin_updown_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ gboolean isDown, GtkWidgetState* state,
+ GtkTextDirection direction)
+{
+ GdkRectangle arrow_rect;
+ GtkStateType state_type = ConvertGtkState(state);
+ GtkShadowType shadow_type = state_type == GTK_STATE_ACTIVE ?
+ GTK_SHADOW_IN : GTK_SHADOW_OUT;
+ GtkStyle* style;
+
+ ensure_spin_widget();
+ style = gSpinWidget->style;
+ gtk_widget_set_direction(gSpinWidget, direction);
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+ gtk_paint_box(style, drawable, state_type, shadow_type, NULL, gSpinWidget,
+ isDown ? "spinbutton_down" : "spinbutton_up",
+ rect->x, rect->y, rect->width, rect->height);
+
+ /* hard code these values */
+ arrow_rect.width = 6;
+ arrow_rect.height = 6;
+ arrow_rect.x = rect->x + (rect->width - arrow_rect.width) / 2;
+ arrow_rect.y = rect->y + (rect->height - arrow_rect.height) / 2;
+ arrow_rect.y += isDown ? -1 : 1;
+
+ gtk_paint_arrow(style, drawable, state_type, shadow_type, NULL,
+ gSpinWidget, "spinbutton",
+ isDown ? GTK_ARROW_DOWN : GTK_ARROW_UP, TRUE,
+ arrow_rect.x, arrow_rect.y,
+ arrow_rect.width, arrow_rect.height);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_scale_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ GtkOrientation flags, GtkTextDirection direction)
+{
+ gint x = 0, y = 0;
+ GtkStateType state_type = ConvertGtkState(state);
+ GtkStyle* style;
+ GtkWidget* widget;
+
+ ensure_scale_widget();
+ widget = ((flags == GTK_ORIENTATION_HORIZONTAL) ? gHScaleWidget : gVScaleWidget);
+ gtk_widget_set_direction(widget, direction);
+
+ style = widget->style;
+
+ if (flags == GTK_ORIENTATION_HORIZONTAL) {
+ x = XTHICKNESS(style);
+ y++;
+ }
+ else {
+ x++;
+ y = YTHICKNESS(style);
+ }
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+ gtk_style_apply_default_background(style, drawable, TRUE, GTK_STATE_NORMAL,
+ cliprect, rect->x, rect->y,
+ rect->width, rect->height);
+
+ gtk_paint_box(style, drawable, GTK_STATE_ACTIVE, GTK_SHADOW_IN, cliprect,
+ widget, "trough", rect->x + x, rect->y + y,
+ rect->width - 2*x, rect->height - 2*y);
+
+ if (state->focused)
+ gtk_paint_focus(style, drawable, state_type, cliprect, widget, "trough",
+ rect->x, rect->y, rect->width, rect->height);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_scale_thumb_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ GtkOrientation flags, GtkTextDirection direction)
+{
+ GtkStateType state_type = ConvertGtkState(state);
+ GtkStyle* style;
+ GtkWidget* widget;
+ gint thumb_width, thumb_height, x, y;
+
+ ensure_scale_widget();
+ widget = ((flags == GTK_ORIENTATION_HORIZONTAL) ? gHScaleWidget : gVScaleWidget);
+ gtk_widget_set_direction(widget, direction);
+
+ style = widget->style;
+
+ /* determine the thumb size, and position the thumb in the center in the opposite axis */
+ if (flags == GTK_ORIENTATION_HORIZONTAL) {
+ moz_gtk_get_scalethumb_metrics(GTK_ORIENTATION_HORIZONTAL, &thumb_width, &thumb_height);
+ x = rect->x;
+ y = rect->y + (rect->height - thumb_height) / 2;
+ }
+ else {
+ moz_gtk_get_scalethumb_metrics(GTK_ORIENTATION_VERTICAL, &thumb_height, &thumb_width);
+ x = rect->x + (rect->width - thumb_width) / 2;
+ y = rect->y;
+ }
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+ gtk_paint_slider(style, drawable, state_type, GTK_SHADOW_OUT, cliprect,
+ widget, (flags == GTK_ORIENTATION_HORIZONTAL) ? "hscale" : "vscale",
+ x, y, thumb_width, thumb_height, flags);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_gripper_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ GtkTextDirection direction)
+{
+ GtkStateType state_type = ConvertGtkState(state);
+ GtkShadowType shadow_type;
+ GtkStyle* style;
+
+ ensure_handlebox_widget();
+ gtk_widget_set_direction(gHandleBoxWidget, direction);
+
+ style = gHandleBoxWidget->style;
+ shadow_type = GTK_HANDLE_BOX(gHandleBoxWidget)->shadow_type;
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+ gtk_paint_box(style, drawable, state_type, shadow_type, cliprect,
+ gHandleBoxWidget, "handlebox_bin", rect->x, rect->y,
+ rect->width, rect->height);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_hpaned_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state)
+{
+ GtkStateType hpaned_state = ConvertGtkState(state);
+
+ ensure_hpaned_widget();
+ gtk_paint_handle(gHPanedWidget->style, drawable, hpaned_state,
+ GTK_SHADOW_NONE, cliprect, gHPanedWidget, "paned",
+ rect->x, rect->y, rect->width, rect->height,
+ GTK_ORIENTATION_VERTICAL);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_vpaned_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state)
+{
+ GtkStateType vpaned_state = ConvertGtkState(state);
+
+ ensure_vpaned_widget();
+ gtk_paint_handle(gVPanedWidget->style, drawable, vpaned_state,
+ GTK_SHADOW_NONE, cliprect, gVPanedWidget, "paned",
+ rect->x, rect->y, rect->width, rect->height,
+ GTK_ORIENTATION_HORIZONTAL);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_caret_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkTextDirection direction)
+{
+ ensure_entry_widget();
+ gtk_draw_insertion_cursor(gEntryWidget, drawable, cliprect,
+ rect, TRUE, direction, FALSE);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_entry_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ GtkWidget* widget, GtkTextDirection direction)
+{
+ GtkStateType bg_state = state->disabled ?
+ GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL;
+ gint x, y, width = rect->width, height = rect->height;
+ GtkStyle* style;
+ gboolean interior_focus;
+ gboolean theme_honors_transparency = FALSE;
+ gint focus_width;
+
+ gtk_widget_set_direction(widget, direction);
+
+ style = widget->style;
+
+ gtk_widget_style_get(widget,
+ "interior-focus", &interior_focus,
+ "focus-line-width", &focus_width,
+ "honors-transparent-bg-hint", &theme_honors_transparency,
+ NULL);
+
+ /* gtkentry.c uses two windows, one for the entire widget and one for the
+ * text area inside it. The background of both windows is set to the "base"
+ * color of the new state in gtk_entry_state_changed, but only the inner
+ * textarea window uses gtk_paint_flat_box when exposed */
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+
+ /* This gets us a lovely greyish disabledish look */
+ gtk_widget_set_sensitive(widget, !state->disabled);
+
+ /* GTK fills the outer widget window with the base color before drawing the widget.
+ * Some older themes rely on this behavior, but many themes nowadays use rounded
+ * corners on their widgets. While most GTK apps are blissfully unaware of this
+ * problem due to their use of the default window background, we render widgets on
+ * many kinds of backgrounds on the web.
+ * If the theme is able to cope with transparency, then we can skip pre-filling
+ * and notify the theme it will paint directly on the canvas. */
+ if (theme_honors_transparency) {
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", TRUE);
+ } else {
+ gdk_draw_rectangle(drawable, style->base_gc[bg_state], TRUE,
+ cliprect->x, cliprect->y, cliprect->width, cliprect->height);
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", FALSE);
+ }
+
+ /* Get the position of the inner window, see _gtk_entry_get_borders */
+ x = XTHICKNESS(style);
+ y = YTHICKNESS(style);
+
+ if (!interior_focus) {
+ x += focus_width;
+ y += focus_width;
+ }
+
+ /* Simulate an expose of the inner window */
+ gtk_paint_flat_box(style, drawable, bg_state, GTK_SHADOW_NONE,
+ cliprect, widget, "entry_bg", rect->x + x,
+ rect->y + y, rect->width - 2*x, rect->height - 2*y);
+
+ /* Now paint the shadow and focus border.
+ * We do like in gtk_entry_draw_frame, we first draw the shadow, a tad
+ * smaller when focused if the focus is not interior, then the focus. */
+ x = rect->x;
+ y = rect->y;
+
+ if (state->focused && !state->disabled) {
+ /* This will get us the lit borders that focused textboxes enjoy on
+ * some themes. */
+ GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
+
+ if (!interior_focus) {
+ /* Indent the border a little bit if we have exterior focus
+ (this is what GTK does to draw native entries) */
+ x += focus_width;
+ y += focus_width;
+ width -= 2 * focus_width;
+ height -= 2 * focus_width;
+ }
+ }
+
+ gtk_paint_shadow(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN,
+ cliprect, widget, "entry", x, y, width, height);
+
+ if (state->focused && !state->disabled) {
+ if (!interior_focus) {
+ gtk_paint_focus(style, drawable, GTK_STATE_NORMAL, cliprect,
+ widget, "entry",
+ rect->x, rect->y, rect->width, rect->height);
+ }
+
+ /* Now unset the focus flag. We don't want other entries to look
+ * like they're focused too! */
+ GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS);
+ }
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_treeview_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ GtkTextDirection direction)
+{
+ gint xthickness, ythickness;
+
+ GtkStyle *style;
+ GtkStateType state_type;
+
+ ensure_tree_view_widget();
+ ensure_scrolled_window_widget();
+
+ gtk_widget_set_direction(gTreeViewWidget, direction);
+ gtk_widget_set_direction(gScrolledWindowWidget, direction);
+
+ /* only handle disabled and normal states, otherwise the whole background
+ * area will be painted differently with other states */
+ state_type = state->disabled ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL;
+
+ /* In GTK the treeview sets the background of the window
+ * which contains the cells to the treeview base color.
+ * If we don't set it here the background color will not be correct.*/
+ gtk_widget_modify_bg(gTreeViewWidget, state_type,
+ &gTreeViewWidget->style->base[state_type]);
+
+ style = gScrolledWindowWidget->style;
+ xthickness = XTHICKNESS(style);
+ ythickness = YTHICKNESS(style);
+
+ TSOffsetStyleGCs(gTreeViewWidget->style, rect->x, rect->y);
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+
+ gtk_paint_flat_box(gTreeViewWidget->style, drawable, state_type,
+ GTK_SHADOW_NONE, cliprect, gTreeViewWidget, "treeview",
+ rect->x + xthickness, rect->y + ythickness,
+ rect->width - 2 * xthickness,
+ rect->height - 2 * ythickness);
+
+ gtk_paint_shadow(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN,
+ cliprect, gScrolledWindowWidget, "scrolled_window",
+ rect->x, rect->y, rect->width, rect->height);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_tree_header_cell_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ gboolean isSorted, GtkTextDirection direction)
+{
+ gtk_tree_view_column_set_sort_indicator(GTK_TREE_VIEW_COLUMN(gMiddleTreeViewColumn),
+ isSorted);
+
+ moz_gtk_button_paint(drawable, rect, cliprect, state, GTK_RELIEF_NORMAL,
+ gTreeHeaderCellWidget, direction);
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_tree_header_sort_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect,
+ GtkWidgetState* state, GtkArrowType flags,
+ GtkTextDirection direction)
+{
+ GdkRectangle arrow_rect;
+ GtkStateType state_type = ConvertGtkState(state);
+ GtkShadowType shadow_type = GTK_SHADOW_IN;
+ GtkArrowType arrow_type = flags;
+ GtkStyle* style;
+
+ ensure_tree_header_cell_widget();
+ gtk_widget_set_direction(gTreeHeaderSortArrowWidget, direction);
+
+ /* hard code these values */
+ arrow_rect.width = 11;
+ arrow_rect.height = 11;
+ arrow_rect.x = rect->x + (rect->width - arrow_rect.width) / 2;
+ arrow_rect.y = rect->y + (rect->height - arrow_rect.height) / 2;
+
+ style = gTreeHeaderSortArrowWidget->style;
+ TSOffsetStyleGCs(style, arrow_rect.x, arrow_rect.y);
+
+ gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
+ gTreeHeaderSortArrowWidget, "arrow", arrow_type, TRUE,
+ arrow_rect.x, arrow_rect.y,
+ arrow_rect.width, arrow_rect.height);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_treeview_expander_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ GtkExpanderStyle expander_state,
+ GtkTextDirection direction)
+{
+ GtkStyle *style;
+ GtkStateType state_type;
+
+ ensure_tree_view_widget();
+ gtk_widget_set_direction(gTreeViewWidget, direction);
+
+ style = gTreeViewWidget->style;
+
+ /* Because the frame we get is of the entire treeview, we can't get the precise
+ * event state of one expander, thus rendering hover and active feedback useless. */
+ state_type = state->disabled ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL;
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+ gtk_paint_expander(style, drawable, state_type, cliprect, gTreeViewWidget, "treeview",
+ rect->x + rect->width / 2, rect->y + rect->height / 2, expander_state);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_expander_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ GtkExpanderStyle expander_state,
+ GtkTextDirection direction)
+{
+ GtkStyle *style;
+ GtkStateType state_type = ConvertGtkState(state);
+
+ ensure_expander_widget();
+ gtk_widget_set_direction(gExpanderWidget, direction);
+
+ style = gExpanderWidget->style;
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+ gtk_paint_expander(style, drawable, state_type, cliprect, gExpanderWidget, "expander",
+ rect->x + rect->width / 2, rect->y + rect->height / 2, expander_state);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_combo_box_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ gboolean ishtml, GtkTextDirection direction)
+{
+ GdkRectangle arrow_rect, real_arrow_rect;
+ gint arrow_size, separator_width = 0;
+ gboolean wide_separators = FALSE;
+ GtkStateType state_type = ConvertGtkState(state);
+ GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
+ GtkStyle* style;
+ GtkRequisition arrow_req;
+
+ ensure_combo_box_widgets();
+
+ /* Also sets the direction on gComboBoxButtonWidget, which is then
+ * inherited by the separator and arrow */
+ moz_gtk_button_paint(drawable, rect, cliprect, state, GTK_RELIEF_NORMAL,
+ gComboBoxButtonWidget, direction);
+
+ calculate_button_inner_rect(gComboBoxButtonWidget,
+ rect, &arrow_rect, direction, ishtml);
+ /* Now arrow_rect contains the inner rect ; we want to correct the width
+ * to what the arrow needs (see gtk_combo_box_size_allocate) */
+ gtk_widget_size_request(gComboBoxArrowWidget, &arrow_req);
+ if (direction == GTK_TEXT_DIR_LTR)
+ arrow_rect.x += arrow_rect.width - arrow_req.width;
+ arrow_rect.width = arrow_req.width;
+
+ calculate_arrow_rect(gComboBoxArrowWidget,
+ &arrow_rect, &real_arrow_rect, direction);
+
+ style = gComboBoxArrowWidget->style;
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+
+ gtk_widget_size_allocate(gComboBoxWidget, rect);
+
+ gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
+ gComboBoxArrowWidget, "arrow", GTK_ARROW_DOWN, TRUE,
+ real_arrow_rect.x, real_arrow_rect.y,
+ real_arrow_rect.width, real_arrow_rect.height);
+
+
+ /* If there is no separator in the theme, there's nothing left to do. */
+ if (!gComboBoxSeparatorWidget)
+ return MOZ_GTK_SUCCESS;
+
+ style = gComboBoxSeparatorWidget->style;
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+
+ if (have_2_10)
+ gtk_widget_style_get(gComboBoxSeparatorWidget,
+ "wide-separators", &wide_separators,
+ "separator-width", &separator_width,
+ NULL);
+
+ if (wide_separators) {
+ if (direction == GTK_TEXT_DIR_LTR)
+ arrow_rect.x -= separator_width;
+ else
+ arrow_rect.x += arrow_rect.width;
+
+ gtk_paint_box(style, drawable,
+ GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT,
+ cliprect, gComboBoxSeparatorWidget, "vseparator",
+ arrow_rect.x, arrow_rect.y,
+ separator_width, arrow_rect.height);
+ } else {
+ if (direction == GTK_TEXT_DIR_LTR)
+ arrow_rect.x -= XTHICKNESS(style);
+ else
+ arrow_rect.x += arrow_rect.width;
+
+ gtk_paint_vline(style, drawable, GTK_STATE_NORMAL, cliprect,
+ gComboBoxSeparatorWidget, "vseparator",
+ arrow_rect.y, arrow_rect.y + arrow_rect.height,
+ arrow_rect.x);
+ }
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_downarrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state)
+{
+ GtkStyle* style;
+ GtkStateType state_type = ConvertGtkState(state);
+ GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
+ GdkRectangle arrow_rect;
+
+ ensure_button_arrow_widget();
+ style = gButtonArrowWidget->style;
+
+ calculate_arrow_rect(gButtonArrowWidget, rect, &arrow_rect,
+ GTK_TEXT_DIR_LTR);
+
+ TSOffsetStyleGCs(style, arrow_rect.x, arrow_rect.y);
+ gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
+ gButtonArrowWidget, "arrow", GTK_ARROW_DOWN, TRUE,
+ arrow_rect.x, arrow_rect.y, arrow_rect.width, arrow_rect.height);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_combo_box_entry_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect,
+ GtkWidgetState* state,
+ gboolean input_focus,
+ GtkTextDirection direction)
+{
+ gint x_displacement, y_displacement;
+ GdkRectangle arrow_rect, real_arrow_rect;
+ GtkStateType state_type = ConvertGtkState(state);
+ GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
+ GtkStyle* style;
+
+ ensure_combo_box_entry_widgets();
+
+ if (input_focus) {
+ /* Some themes draw a complementary focus ring for the dropdown button
+ * when the dropdown entry has focus */
+ GTK_WIDGET_SET_FLAGS(gComboBoxEntryTextareaWidget, GTK_HAS_FOCUS);
+ }
+
+ moz_gtk_button_paint(drawable, rect, cliprect, state, GTK_RELIEF_NORMAL,
+ gComboBoxEntryButtonWidget, direction);
+
+ if (input_focus)
+ GTK_WIDGET_UNSET_FLAGS(gComboBoxEntryTextareaWidget, GTK_HAS_FOCUS);
+
+ calculate_button_inner_rect(gComboBoxEntryButtonWidget,
+ rect, &arrow_rect, direction, FALSE);
+ if (state_type == GTK_STATE_ACTIVE) {
+ gtk_widget_style_get(gComboBoxEntryButtonWidget,
+ "child-displacement-x", &x_displacement,
+ "child-displacement-y", &y_displacement,
+ NULL);
+ arrow_rect.x += x_displacement;
+ arrow_rect.y += y_displacement;
+ }
+
+ calculate_arrow_rect(gComboBoxEntryArrowWidget,
+ &arrow_rect, &real_arrow_rect, direction);
+
+ style = gComboBoxEntryArrowWidget->style;
+ TSOffsetStyleGCs(style, real_arrow_rect.x, real_arrow_rect.y);
+
+ gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
+ gComboBoxEntryArrowWidget, "arrow", GTK_ARROW_DOWN, TRUE,
+ real_arrow_rect.x, real_arrow_rect.y,
+ real_arrow_rect.width, real_arrow_rect.height);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_container_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ gboolean isradio, GtkTextDirection direction)
+{
+ GtkStateType state_type = ConvertGtkState(state);
+ GtkStyle* style;
+ GtkWidget *widget;
+ gboolean interior_focus;
+ gint focus_width, focus_pad;
+
+ if (isradio) {
+ ensure_radiobutton_widget();
+ widget = gRadiobuttonWidget;
+ } else {
+ ensure_checkbox_widget();
+ widget = gCheckboxWidget;
+ }
+ gtk_widget_set_direction(widget, direction);
+
+ style = widget->style;
+ moz_gtk_widget_get_focus(widget, &interior_focus, &focus_width,
+ &focus_pad);
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+
+ /* The detail argument for the gtk_paint_* calls below are "checkbutton"
+ even for radio buttons, to match what gtk does. */
+
+ /* this is for drawing a prelight box */
+ if (state_type == GTK_STATE_PRELIGHT || state_type == GTK_STATE_ACTIVE) {
+ gtk_paint_flat_box(style, drawable, GTK_STATE_PRELIGHT,
+ GTK_SHADOW_ETCHED_OUT, cliprect, widget,
+ "checkbutton",
+ rect->x, rect->y, rect->width, rect->height);
+ }
+
+ if (state_type != GTK_STATE_NORMAL && state_type != GTK_STATE_PRELIGHT)
+ state_type = GTK_STATE_NORMAL;
+
+ if (state->focused && !interior_focus) {
+ gtk_paint_focus(style, drawable, state_type, cliprect, widget,
+ "checkbutton",
+ rect->x, rect->y, rect->width, rect->height);
+ }
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_toggle_label_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ gboolean isradio, GtkTextDirection direction)
+{
+ GtkStateType state_type;
+ GtkStyle *style;
+ GtkWidget *widget;
+ gboolean interior_focus;
+
+ if (!state->focused)
+ return MOZ_GTK_SUCCESS;
+
+ if (isradio) {
+ ensure_radiobutton_widget();
+ widget = gRadiobuttonWidget;
+ } else {
+ ensure_checkbox_widget();
+ widget = gCheckboxWidget;
+ }
+ gtk_widget_set_direction(widget, direction);
+
+ gtk_widget_style_get(widget, "interior-focus", &interior_focus, NULL);
+ if (!interior_focus)
+ return MOZ_GTK_SUCCESS;
+
+ state_type = ConvertGtkState(state);
+
+ style = widget->style;
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+
+ /* Always "checkbutton" to match gtkcheckbutton.c */
+ gtk_paint_focus(style, drawable, state_type, cliprect, widget,
+ "checkbutton",
+ rect->x, rect->y, rect->width, rect->height);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_toolbar_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkTextDirection direction)
+{
+ GtkStyle* style;
+ GtkShadowType shadow_type;
+
+ ensure_toolbar_widget();
+ gtk_widget_set_direction(gToolbarWidget, direction);
+
+ style = gToolbarWidget->style;
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+
+ gtk_style_apply_default_background(style, drawable, TRUE,
+ GTK_STATE_NORMAL,
+ cliprect, rect->x, rect->y,
+ rect->width, rect->height);
+
+ gtk_widget_style_get(gToolbarWidget, "shadow-type", &shadow_type, NULL);
+
+ gtk_paint_box (style, drawable, GTK_STATE_NORMAL, shadow_type,
+ cliprect, gToolbarWidget, "toolbar",
+ rect->x, rect->y, rect->width, rect->height);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_toolbar_separator_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect,
+ GtkTextDirection direction)
+{
+ GtkStyle* style;
+ gint separator_width = 0;
+ gint paint_width;
+ gboolean wide_separators = FALSE;
+
+ /* Defined as constants in GTK+ 2.10.14 */
+ const double start_fraction = 0.2;
+ const double end_fraction = 0.8;
+
+ ensure_toolbar_separator_widget();
+ gtk_widget_set_direction(gToolbarSeparatorWidget, direction);
+
+ style = gToolbarSeparatorWidget->style;
+
+ if (have_2_10)
+ gtk_widget_style_get(gToolbarWidget,
+ "wide-separators", &wide_separators,
+ "separator-width", &separator_width,
+ NULL);
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+
+ if (wide_separators) {
+ if (separator_width > rect->width)
+ separator_width = rect->width;
+
+ gtk_paint_box(style, drawable,
+ GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT,
+ cliprect, gToolbarWidget, "vseparator",
+ rect->x + (rect->width - separator_width) / 2,
+ rect->y + rect->height * start_fraction,
+ separator_width,
+ rect->height * (end_fraction - start_fraction));
+
+ } else {
+ paint_width = style->xthickness;
+
+ if (paint_width > rect->width)
+ paint_width = rect->width;
+
+ gtk_paint_vline(style, drawable,
+ GTK_STATE_NORMAL, cliprect, gToolbarSeparatorWidget,
+ "toolbar",
+ rect->y + rect->height * start_fraction,
+ rect->y + rect->height * end_fraction,
+ rect->x + (rect->width - paint_width) / 2);
+ }
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_tooltip_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkTextDirection direction)
+{
+ GtkStyle* style;
+
+ ensure_tooltip_widget();
+ gtk_widget_set_direction(gTooltipWidget, direction);
+
+ style = gtk_rc_get_style_by_paths(gtk_settings_get_default(),
+ "gtk-tooltips", "GtkWindow",
+ GTK_TYPE_WINDOW);
+
+ style = gtk_style_attach(style, gTooltipWidget->window);
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+ gtk_paint_flat_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+ cliprect, gTooltipWidget, "tooltip",
+ rect->x, rect->y, rect->width, rect->height);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_resizer_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ GtkTextDirection direction)
+{
+ GtkStyle* style;
+ GtkStateType state_type = ConvertGtkState(state);
+
+ ensure_window_widget();
+ gtk_widget_set_direction(gProtoWindow, direction);
+
+ style = gProtoWindow->style;
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+
+ gtk_paint_resize_grip(style, drawable, state_type, cliprect, gProtoWindow,
+ NULL, (direction == GTK_TEXT_DIR_LTR) ?
+ GDK_WINDOW_EDGE_SOUTH_EAST :
+ GDK_WINDOW_EDGE_SOUTH_WEST,
+ rect->x, rect->y, rect->width, rect->height);
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_frame_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkTextDirection direction)
+{
+ GtkStyle* style;
+ GtkShadowType shadow_type;
+
+ ensure_frame_widget();
+ gtk_widget_set_direction(gFrameWidget, direction);
+
+ style = gFrameWidget->style;
+
+ gtk_widget_style_get(gStatusbarWidget, "shadow-type", &shadow_type, NULL);
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+ gtk_paint_shadow(style, drawable, GTK_STATE_NORMAL, shadow_type,
+ cliprect, gFrameWidget, "frame", rect->x, rect->y,
+ rect->width, rect->height);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_progressbar_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkTextDirection direction)
+{
+ GtkStyle* style;
+
+ ensure_progress_widget();
+ gtk_widget_set_direction(gProgressWidget, direction);
+
+ style = gProgressWidget->style;
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+ gtk_paint_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN,
+ cliprect, gProgressWidget, "trough", rect->x, rect->y,
+ rect->width, rect->height);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_progress_chunk_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkTextDirection direction)
+{
+ GtkStyle* style;
+
+ ensure_progress_widget();
+ gtk_widget_set_direction(gProgressWidget, direction);
+
+ style = gProgressWidget->style;
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+ gtk_paint_box(style, drawable, GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
+ cliprect, gProgressWidget, "bar", rect->x, rect->y,
+ rect->width, rect->height);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+gint
+moz_gtk_get_tab_thickness(void)
+{
+ ensure_tab_widget();
+ if (YTHICKNESS(gTabWidget->style) < 2)
+ return 2; /* some themes don't set ythickness correctly */
+
+ return YTHICKNESS(gTabWidget->style);
+}
+
+static gint
+moz_gtk_tab_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkTabFlags flags,
+ GtkTextDirection direction)
+{
+ /* When the tab isn't selected, we just draw a notebook extension.
+ * When it is selected, we overwrite the adjacent border of the tabpanel
+ * touching the tab with a pierced border (called "the gap") to make the
+ * tab appear physically attached to the tabpanel; see details below. */
+
+ GtkStyle* style;
+
+ ensure_tab_widget();
+ gtk_widget_set_direction(gTabWidget, direction);
+
+ style = gTabWidget->style;
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+
+ if ((flags & MOZ_GTK_TAB_SELECTED) == 0) {
+ /* Only draw the tab */
+ gtk_paint_extension(style, drawable, GTK_STATE_ACTIVE, GTK_SHADOW_OUT,
+ cliprect, gTabWidget, "tab",
+ rect->x, rect->y, rect->width, rect->height,
+ (flags & MOZ_GTK_TAB_BOTTOM) ?
+ GTK_POS_TOP : GTK_POS_BOTTOM );
+ } else {
+ /* Draw the tab and the gap
+ * We want the gap to be positionned exactly on the tabpanel top
+ * border; since tabbox.css may set a negative margin so that the tab
+ * frame rect already overlaps the tabpanel frame rect, we need to take
+ * that into account when drawing. To that effect, nsNativeThemeGTK
+ * passes us this negative margin (bmargin in the graphic below) in the
+ * lowest bits of |flags|. We use it to set gap_voffset, the distance
+ * between the top of the gap and the bottom of the tab (resp. the
+ * bottom of the gap and the top of the tab when we draw a bottom tab),
+ * while ensuring that the gap always touches the border of the tab,
+ * i.e. 0 <= gap_voffset <= gap_height, to avoid surprinsing results
+ * with big negative or positive margins.
+ * Here is a graphical explanation in the case of top tabs:
+ * ___________________________
+ * / \
+ * | T A B |
+ * ----------|. . . . . . . . . . . . . . .|----- top of tabpanel
+ * : ^ bmargin : ^
+ * : | (-negative margin, : |
+ * bottom : v passed in flags) : | gap_height
+ * of -> :.............................: | (the size of the
+ * the tab . part of the gap . | tabpanel top border)
+ * . outside of the tab . v
+ * ----------------------------------------------
+ *
+ * To draw the gap, we use gtk_paint_box_gap(), see comment in
+ * moz_gtk_tabpanels_paint(). This box_gap is made 3 * gap_height tall,
+ * which should suffice to ensure that the only visible border is the
+ * pierced one. If the tab is in the middle, we make the box_gap begin
+ * a bit to the left of the tab and end a bit to the right, adjusting
+ * the gap position so it still is under the tab, because we want the
+ * rendering of a gap in the middle of a tabpanel. This is the role of
+ * the gints gap_{l,r}_offset. On the contrary, if the tab is the
+ * first, we align the start border of the box_gap with the start
+ * border of the tab (left if LTR, right if RTL), by setting the
+ * appropriate offset to 0.*/
+ gint gap_loffset, gap_roffset, gap_voffset, gap_height;
+
+ /* Get height needed by the gap */
+ gap_height = moz_gtk_get_tab_thickness();
+
+ /* Extract gap_voffset from the first bits of flags */
+ gap_voffset = flags & MOZ_GTK_TAB_MARGIN_MASK;
+ if (gap_voffset > gap_height)
+ gap_voffset = gap_height;
+
+ /* Set gap_{l,r}_offset to appropriate values */
+ gap_loffset = gap_roffset = 20; /* should be enough */
+ if (flags & MOZ_GTK_TAB_FIRST) {
+ if (direction == GTK_TEXT_DIR_RTL)
+ gap_roffset = 0;
+ else
+ gap_loffset = 0;
+ }
+
+ if (flags & MOZ_GTK_TAB_BOTTOM) {
+ /* Enlarge the cliprect to have room for the full gap height */
+ cliprect->height += gap_height - gap_voffset;
+ cliprect->y -= gap_height - gap_voffset;
+
+ /* Draw the tab */
+ gtk_paint_extension(style, drawable, GTK_STATE_NORMAL,
+ GTK_SHADOW_OUT, cliprect, gTabWidget, "tab",
+ rect->x, rect->y + gap_voffset, rect->width,
+ rect->height - gap_voffset, GTK_POS_TOP);
+
+ /* Draw the gap; erase with background color before painting in
+ * case theme does not */
+ gtk_style_apply_default_background(style, drawable, TRUE,
+ GTK_STATE_NORMAL, cliprect,
+ rect->x,
+ rect->y + gap_voffset
+ - gap_height,
+ rect->width, gap_height);
+ gtk_paint_box_gap(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+ cliprect, gTabWidget, "notebook",
+ rect->x - gap_loffset,
+ rect->y + gap_voffset - 3 * gap_height,
+ rect->width + gap_loffset + gap_roffset,
+ 3 * gap_height, GTK_POS_BOTTOM,
+ gap_loffset, rect->width);
+ } else {
+ /* Enlarge the cliprect to have room for the full gap height */
+ cliprect->height += gap_height - gap_voffset;
+
+ /* Draw the tab */
+ gtk_paint_extension(style, drawable, GTK_STATE_NORMAL,
+ GTK_SHADOW_OUT, cliprect, gTabWidget, "tab",
+ rect->x, rect->y, rect->width,
+ rect->height - gap_voffset, GTK_POS_BOTTOM);
+
+ /* Draw the gap; erase with background color before painting in
+ * case theme does not */
+ gtk_style_apply_default_background(style, drawable, TRUE,
+ GTK_STATE_NORMAL, cliprect,
+ rect->x,
+ rect->y + rect->height
+ - gap_voffset,
+ rect->width, gap_height);
+ gtk_paint_box_gap(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+ cliprect, gTabWidget, "notebook",
+ rect->x - gap_loffset,
+ rect->y + rect->height - gap_voffset,
+ rect->width + gap_loffset + gap_roffset,
+ 3 * gap_height, GTK_POS_TOP,
+ gap_loffset, rect->width);
+ }
+
+ }
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_tabpanels_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkTextDirection direction)
+{
+ /* We use gtk_paint_box_gap() to draw the tabpanels widget. gtk_paint_box()
+ * draws an all-purpose box, which a lot of themes render differently.
+ * A zero-width gap is still visible in most themes, so we hide it to the
+ * left (10px should be enough) */
+ GtkStyle* style;
+
+ ensure_tab_widget();
+ gtk_widget_set_direction(gTabWidget, direction);
+
+ style = gTabWidget->style;
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+ gtk_paint_box_gap(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+ cliprect, gTabWidget, "notebook", rect->x, rect->y,
+ rect->width, rect->height,
+ GTK_POS_TOP, -10, 0);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_tab_scroll_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ GtkArrowType arrow_type,
+ GtkTextDirection direction)
+{
+ GtkStateType state_type = ConvertGtkState(state);
+ GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
+ GtkStyle* style;
+ gint arrow_size = MIN(rect->width, rect->height);
+ gint x = rect->x + (rect->width - arrow_size) / 2;
+ gint y = rect->y + (rect->height - arrow_size) / 2;
+
+ ensure_tab_widget();
+
+ style = gTabWidget->style;
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+
+ if (direction == GTK_TEXT_DIR_RTL) {
+ arrow_type = (arrow_type == GTK_ARROW_LEFT) ?
+ GTK_ARROW_RIGHT : GTK_ARROW_LEFT;
+ }
+
+ gtk_paint_arrow(style, drawable, state_type, shadow_type, NULL,
+ gTabWidget, "notebook", arrow_type, TRUE,
+ x, y, arrow_size, arrow_size);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_menu_bar_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkTextDirection direction)
+{
+ GtkStyle* style;
+ GtkShadowType shadow_type;
+ ensure_menu_bar_widget();
+ gtk_widget_set_direction(gMenuBarWidget, direction);
+
+ gtk_widget_style_get(gMenuBarWidget, "shadow-type", &shadow_type, NULL);
+
+ style = gMenuBarWidget->style;
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+ gtk_style_apply_default_background(style, drawable, TRUE, GTK_STATE_NORMAL,
+ cliprect, rect->x, rect->y,
+ rect->width, rect->height);
+
+ gtk_paint_box(style, drawable, GTK_STATE_NORMAL, shadow_type,
+ cliprect, gMenuBarWidget, "menubar", rect->x, rect->y,
+ rect->width, rect->height);
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_menu_popup_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkTextDirection direction)
+{
+ GtkStyle* style;
+ ensure_menu_popup_widget();
+ gtk_widget_set_direction(gMenuPopupWidget, direction);
+
+ style = gMenuPopupWidget->style;
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+ gtk_style_apply_default_background(style, drawable, TRUE, GTK_STATE_NORMAL,
+ cliprect, rect->x, rect->y,
+ rect->width, rect->height);
+ gtk_paint_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+ cliprect, gMenuPopupWidget, "menu",
+ rect->x, rect->y, rect->width, rect->height);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_menu_separator_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkTextDirection direction)
+{
+ GtkStyle* style;
+ gboolean wide_separators = FALSE;
+ gint separator_height = 0;
+ guint horizontal_padding = 0;
+ gint paint_height;
+
+ ensure_menu_separator_widget();
+ gtk_widget_set_direction(gMenuSeparatorWidget, direction);
+
+ style = gMenuSeparatorWidget->style;
+
+ if (have_2_10)
+ gtk_widget_style_get(gMenuSeparatorWidget,
+ "wide-separators", &wide_separators,
+ "separator-height", &separator_height,
+ NULL);
+
+ gtk_widget_style_get(gMenuSeparatorWidget,
+ "horizontal-padding", &horizontal_padding,
+ NULL);
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+
+ if (wide_separators) {
+ if (separator_height > rect->height)
+ separator_height = rect->height;
+
+ gtk_paint_box(style, drawable,
+ GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT,
+ cliprect, gMenuSeparatorWidget, "hseparator",
+ rect->x + horizontal_padding + style->xthickness,
+ rect->y + (rect->height - separator_height - style->ythickness) / 2,
+ rect->width - 2 * (horizontal_padding + style->xthickness),
+ separator_height);
+ } else {
+ paint_height = style->ythickness;
+ if (paint_height > rect->height)
+ paint_height = rect->height;
+
+ gtk_paint_hline(style, drawable,
+ GTK_STATE_NORMAL, cliprect, gMenuSeparatorWidget,
+ "menuitem",
+ rect->x + horizontal_padding + style->xthickness,
+ rect->x + rect->width - horizontal_padding - style->xthickness - 1,
+ rect->y + (rect->height - style->ythickness) / 2);
+ }
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_menu_item_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ gint flags, GtkTextDirection direction)
+{
+ GtkStyle* style;
+ GtkShadowType shadow_type;
+ GtkWidget* item_widget;
+
+ if (state->inHover && !state->disabled) {
+ if (flags & MOZ_TOPLEVEL_MENU_ITEM) {
+ ensure_menu_bar_item_widget();
+ item_widget = gMenuBarItemWidget;
+ } else {
+ ensure_menu_item_widget();
+ item_widget = gMenuItemWidget;
+ }
+ gtk_widget_set_direction(item_widget, direction);
+
+ style = item_widget->style;
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+
+ gtk_widget_style_get(item_widget, "selected-shadow-type",
+ &shadow_type, NULL);
+
+ gtk_paint_box(style, drawable, GTK_STATE_PRELIGHT, shadow_type,
+ cliprect, item_widget, "menuitem", rect->x, rect->y,
+ rect->width, rect->height);
+ }
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_menu_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ GtkTextDirection direction)
+{
+ GtkStyle* style;
+ GtkStateType state_type = ConvertGtkState(state);
+
+ ensure_menu_item_widget();
+ gtk_widget_set_direction(gMenuItemWidget, direction);
+
+ style = gMenuItemWidget->style;
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+ gtk_paint_arrow(style, drawable, state_type,
+ (state_type == GTK_STATE_PRELIGHT) ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
+ cliprect, gMenuItemWidget, "menuitem",
+ (direction == GTK_TEXT_DIR_LTR) ? GTK_ARROW_RIGHT : GTK_ARROW_LEFT,
+ TRUE, rect->x, rect->y, rect->width, rect->height);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_check_menu_item_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ gboolean checked, gboolean isradio,
+ GtkTextDirection direction)
+{
+ GtkStateType state_type = ConvertGtkState(state);
+ GtkStyle* style;
+ GtkShadowType shadow_type = (checked)?GTK_SHADOW_IN:GTK_SHADOW_OUT;
+ gint offset;
+ gint indicator_size;
+ gint x, y;
+
+ moz_gtk_menu_item_paint(drawable, rect, cliprect, state, FALSE, direction);
+
+ ensure_check_menu_item_widget();
+ gtk_widget_set_direction(gCheckMenuItemWidget, direction);
+
+ gtk_widget_style_get (gCheckMenuItemWidget,
+ "indicator-size", &indicator_size,
+ NULL);
+
+ if (checked || GTK_CHECK_MENU_ITEM(gCheckMenuItemWidget)->always_show_toggle) {
+ style = gCheckMenuItemWidget->style;
+
+ offset = GTK_CONTAINER(gCheckMenuItemWidget)->border_width +
+ gCheckMenuItemWidget->style->xthickness + 2;
+
+ /* while normally this "3" would be the horizontal-padding style value, passing it to Gecko
+ as the value of menuitem padding causes problems with dropdowns (bug 406129), so in the menu.css
+ file this is hardcoded as 3px. Yes it sucks, but we don't really have a choice. */
+ x = (direction == GTK_TEXT_DIR_RTL) ?
+ rect->width - indicator_size - offset - 3: rect->x + offset + 3;
+ y = rect->y + (rect->height - indicator_size) / 2;
+
+ TSOffsetStyleGCs(style, x, y);
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gCheckMenuItemWidget),
+ checked);
+
+ if (isradio) {
+ gtk_paint_option(style, drawable, state_type, shadow_type, cliprect,
+ gCheckMenuItemWidget, "option",
+ x, y, indicator_size, indicator_size);
+ } else {
+ gtk_paint_check(style, drawable, state_type, shadow_type, cliprect,
+ gCheckMenuItemWidget, "check",
+ x, y, indicator_size, indicator_size);
+ }
+ }
+
+ return MOZ_GTK_SUCCESS;
+}
+
+static gint
+moz_gtk_window_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkTextDirection direction)
+{
+ GtkStyle* style;
+
+ ensure_window_widget();
+ gtk_widget_set_direction(gProtoWindow, direction);
+
+ style = gProtoWindow->style;
+
+ TSOffsetStyleGCs(style, rect->x, rect->y);
+ gtk_style_apply_default_background(style, drawable, TRUE,
+ GTK_STATE_NORMAL,
+ cliprect, rect->x, rect->y,
+ rect->width, rect->height);
+ return MOZ_GTK_SUCCESS;
+}
+
+gint
+moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
+ gint* right, gint* bottom, GtkTextDirection direction,
+ gboolean inhtml)
+{
+ GtkWidget* w;
+
+ switch (widget) {
+ case MOZ_GTK_BUTTON:
+ {
+ GtkBorder inner_border;
+ gboolean interior_focus;
+ gint focus_width, focus_pad;
+
+ ensure_button_widget();
+ *left = *top = *right = *bottom = GTK_CONTAINER(gButtonWidget)->border_width;
+
+ /* Don't add this padding in HTML, otherwise the buttons will
+ become too big and stuff the layout. */
+ if (!inhtml) {
+ moz_gtk_widget_get_focus(gButtonWidget, &interior_focus, &focus_width, &focus_pad);
+ moz_gtk_button_get_inner_border(gButtonWidget, &inner_border);
+ *left += focus_width + focus_pad + inner_border.left;
+ *right += focus_width + focus_pad + inner_border.right;
+ *top += focus_width + focus_pad + inner_border.top;
+ *bottom += focus_width + focus_pad + inner_border.bottom;
+ }
+
+ *left += gButtonWidget->style->xthickness;
+ *right += gButtonWidget->style->xthickness;
+ *top += gButtonWidget->style->ythickness;
+ *bottom += gButtonWidget->style->ythickness;
+ return MOZ_GTK_SUCCESS;
+ }
+ case MOZ_GTK_ENTRY:
+ ensure_entry_widget();
+ w = gEntryWidget;
+ break;
+ case MOZ_GTK_TREEVIEW:
+ ensure_tree_view_widget();
+ w = gTreeViewWidget;
+ break;
+ case MOZ_GTK_TREE_HEADER_CELL:
+ {
+ /* A Tree Header in GTK is just a different styled button
+ * It must be placed in a TreeView for getting the correct style
+ * assigned.
+ * That is why the following code is the same as for MOZ_GTK_BUTTON.
+ * */
+
+ GtkBorder inner_border;
+ gboolean interior_focus;
+ gint focus_width, focus_pad;
+
+ ensure_tree_header_cell_widget();
+ *left = *top = *right = *bottom = GTK_CONTAINER(gTreeHeaderCellWidget)->border_width;
+
+ moz_gtk_widget_get_focus(gTreeHeaderCellWidget, &interior_focus, &focus_width, &focus_pad);
+ moz_gtk_button_get_inner_border(gTreeHeaderCellWidget, &inner_border);
+ *left += focus_width + focus_pad + inner_border.left;
+ *right += focus_width + focus_pad + inner_border.right;
+ *top += focus_width + focus_pad + inner_border.top;
+ *bottom += focus_width + focus_pad + inner_border.bottom;
+
+ *left += gTreeHeaderCellWidget->style->xthickness;
+ *right += gTreeHeaderCellWidget->style->xthickness;
+ *top += gTreeHeaderCellWidget->style->ythickness;
+ *bottom += gTreeHeaderCellWidget->style->ythickness;
+ return MOZ_GTK_SUCCESS;
+ }
+ case MOZ_GTK_TREE_HEADER_SORTARROW:
+ ensure_tree_header_cell_widget();
+ w = gTreeHeaderSortArrowWidget;
+ break;
+ case MOZ_GTK_DROPDOWN_ENTRY:
+ ensure_combo_box_entry_widgets();
+ w = gComboBoxEntryTextareaWidget;
+ break;
+ case MOZ_GTK_DROPDOWN_ARROW:
+ ensure_combo_box_entry_widgets();
+ w = gComboBoxEntryButtonWidget;
+ break;
+ case MOZ_GTK_DROPDOWN:
+ {
+ /* We need to account for the arrow on the dropdown, so text
+ * doesn't come too close to the arrow, or in some cases spill
+ * into the arrow. */
+ gboolean ignored_interior_focus, wide_separators = FALSE;
+ gint focus_width, focus_pad, separator_width;
+ GtkRequisition arrow_req;
+
+ ensure_combo_box_widgets();
+
+ *left = GTK_CONTAINER(gComboBoxButtonWidget)->border_width;
+
+ if (!inhtml) {
+ moz_gtk_widget_get_focus(gComboBoxButtonWidget,
+ &ignored_interior_focus,
+ &focus_width, &focus_pad);
+ *left += focus_width + focus_pad;
+ }
+
+ *top = *left + gComboBoxButtonWidget->style->ythickness;
+ *left += gComboBoxButtonWidget->style->xthickness;
+
+ *right = *left; *bottom = *top;
+
+ /* If there is no separator, don't try to count its width. */
+ separator_width = 0;
+ if (gComboBoxSeparatorWidget) {
+ if (have_2_10)
+ gtk_widget_style_get(gComboBoxSeparatorWidget,
+ "wide-separators", &wide_separators,
+ "separator-width", &separator_width,
+ NULL);
+
+ if (!wide_separators)
+ separator_width =
+ XTHICKNESS(gComboBoxSeparatorWidget->style);
+ }
+
+ gtk_widget_size_request(gComboBoxArrowWidget, &arrow_req);
+
+ if (direction == GTK_TEXT_DIR_RTL)
+ *left += separator_width + arrow_req.width;
+ else
+ *right += separator_width + arrow_req.width;
+
+ return MOZ_GTK_SUCCESS;
+ }
+ case MOZ_GTK_TABPANELS:
+ ensure_tab_widget();
+ w = gTabWidget;
+ break;
+ case MOZ_GTK_PROGRESSBAR:
+ ensure_progress_widget();
+ w = gProgressWidget;
+ break;
+ case MOZ_GTK_SPINBUTTON_ENTRY:
+ case MOZ_GTK_SPINBUTTON_UP:
+ case MOZ_GTK_SPINBUTTON_DOWN:
+ ensure_spin_widget();
+ w = gSpinWidget;
+ break;
+ case MOZ_GTK_SCALE_HORIZONTAL:
+ ensure_scale_widget();
+ w = gHScaleWidget;
+ break;
+ case MOZ_GTK_SCALE_VERTICAL:
+ ensure_scale_widget();
+ w = gVScaleWidget;
+ break;
+ case MOZ_GTK_FRAME:
+ ensure_frame_widget();
+ w = gFrameWidget;
+ break;
+ case MOZ_GTK_CHECKBUTTON_LABEL:
+ case MOZ_GTK_RADIOBUTTON_LABEL:
+ {
+ gboolean interior_focus;
+ gint focus_width, focus_pad;
+
+ /* If the focus is interior, then the label has a border of
+ (focus_width + focus_pad). */
+ if (widget == MOZ_GTK_CHECKBUTTON_LABEL) {
+ ensure_checkbox_widget();
+ moz_gtk_widget_get_focus(gCheckboxWidget, &interior_focus,
+ &focus_width, &focus_pad);
+ }
+ else {
+ ensure_radiobutton_widget();
+ moz_gtk_widget_get_focus(gRadiobuttonWidget, &interior_focus,
+ &focus_width, &focus_pad);
+ }
+
+ if (interior_focus)
+ *left = *top = *right = *bottom = (focus_width + focus_pad);
+ else
+ *left = *top = *right = *bottom = 0;
+
+ return MOZ_GTK_SUCCESS;
+ }
+
+ case MOZ_GTK_CHECKBUTTON_CONTAINER:
+ case MOZ_GTK_RADIOBUTTON_CONTAINER:
+ {
+ gboolean interior_focus;
+ gint focus_width, focus_pad;
+
+ /* If the focus is _not_ interior, then the container has a border
+ of (focus_width + focus_pad). */
+ if (widget == MOZ_GTK_CHECKBUTTON_CONTAINER) {
+ ensure_checkbox_widget();
+ moz_gtk_widget_get_focus(gCheckboxWidget, &interior_focus,
+ &focus_width, &focus_pad);
+ w = gCheckboxWidget;
+ } else {
+ ensure_radiobutton_widget();
+ moz_gtk_widget_get_focus(gRadiobuttonWidget, &interior_focus,
+ &focus_width, &focus_pad);
+ w = gRadiobuttonWidget;
+ }
+
+ *left = *top = *right = *bottom = GTK_CONTAINER(w)->border_width;
+
+ if (!interior_focus) {
+ *left += (focus_width + focus_pad);
+ *right += (focus_width + focus_pad);
+ *top += (focus_width + focus_pad);
+ *bottom += (focus_width + focus_pad);
+ }
+
+ return MOZ_GTK_SUCCESS;
+ }
+ case MOZ_GTK_MENUPOPUP:
+ ensure_menu_popup_widget();
+ w = gMenuPopupWidget;
+ break;
+ case MOZ_GTK_MENUITEM:
+ ensure_menu_item_widget();
+ ensure_menu_bar_item_widget();
+ w = gMenuItemWidget;
+ break;
+ case MOZ_GTK_CHECKMENUITEM:
+ case MOZ_GTK_RADIOMENUITEM:
+ ensure_check_menu_item_widget();
+ w = gCheckMenuItemWidget;
+ break;
+ case MOZ_GTK_TAB:
+ ensure_tab_widget();
+ w = gTabWidget;
+ break;
+ /* These widgets have no borders, since they are not containers. */
+ case MOZ_GTK_SPLITTER_HORIZONTAL:
+ case MOZ_GTK_SPLITTER_VERTICAL:
+ case MOZ_GTK_CHECKBUTTON:
+ case MOZ_GTK_RADIOBUTTON:
+ case MOZ_GTK_SCROLLBAR_BUTTON:
+ case MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL:
+ case MOZ_GTK_SCROLLBAR_TRACK_VERTICAL:
+ case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL:
+ case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL:
+ case MOZ_GTK_SCALE_THUMB_HORIZONTAL:
+ case MOZ_GTK_SCALE_THUMB_VERTICAL:
+ case MOZ_GTK_GRIPPER:
+ case MOZ_GTK_PROGRESS_CHUNK:
+ case MOZ_GTK_EXPANDER:
+ case MOZ_GTK_TREEVIEW_EXPANDER:
+ case MOZ_GTK_TOOLBAR_SEPARATOR:
+ case MOZ_GTK_MENUSEPARATOR:
+ /* These widgets have no borders.*/
+ case MOZ_GTK_SPINBUTTON:
+ case MOZ_GTK_TOOLTIP:
+ case MOZ_GTK_WINDOW:
+ case MOZ_GTK_RESIZER:
+ case MOZ_GTK_MENUARROW:
+ case MOZ_GTK_TOOLBARBUTTON_ARROW:
+ case MOZ_GTK_TOOLBAR:
+ case MOZ_GTK_MENUBAR:
+ case MOZ_GTK_TAB_SCROLLARROW:
+ case MOZ_GTK_ENTRY_CARET:
+ *left = *top = *right = *bottom = 0;
+ return MOZ_GTK_SUCCESS;
+ default:
+ g_warning("Unsupported widget type: %d", widget);
+ return MOZ_GTK_UNKNOWN_WIDGET;
+ }
+
+ *right = *left = XTHICKNESS(w->style);
+ *bottom = *top = YTHICKNESS(w->style);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+gint
+moz_gtk_get_combo_box_entry_button_size(gint* width, gint* height)
+{
+ /*
+ * We get the requisition of the drop down button, which includes
+ * all padding, border and focus line widths the button uses,
+ * as well as the minimum arrow size and its padding
+ * */
+ GtkRequisition requisition;
+ ensure_combo_box_entry_widgets();
+
+ gtk_widget_size_request(gComboBoxEntryButtonWidget, &requisition);
+ *width = requisition.width;
+ *height = requisition.height;
+
+ return MOZ_GTK_SUCCESS;
+}
+
+gint
+moz_gtk_get_tab_scroll_arrow_size(gint* width, gint* height)
+{
+ gint arrow_size = 16;
+
+ ensure_tab_widget();
+ if (have_2_10)
+ gtk_widget_style_get(gTabWidget,
+ "scroll-arrow-hlength", &arrow_size,
+ NULL);
+
+ *height = *width = arrow_size;
+
+ return MOZ_GTK_SUCCESS;
+}
+
+gint
+moz_gtk_get_downarrow_size(gint* width, gint* height)
+{
+ GtkRequisition requisition;
+ ensure_button_arrow_widget();
+
+ gtk_widget_size_request(gButtonArrowWidget, &requisition);
+ *width = requisition.width;
+ *height = requisition.height;
+
+ return MOZ_GTK_SUCCESS;
+}
+
+gint
+moz_gtk_get_toolbar_separator_width(gint* size)
+{
+ gboolean wide_separators = FALSE;
+ gint separator_width = 0;
+ GtkStyle* style;
+
+ ensure_toolbar_widget();
+
+ style = gToolbarWidget->style;
+
+ if (have_2_10)
+ gtk_widget_style_get(gToolbarWidget,
+ "wide-separators", &wide_separators,
+ "separator-width", &separator_width,
+ NULL);
+
+ gtk_widget_style_get(gToolbarWidget,
+ "space-size", size,
+ NULL);
+
+ /* Just in case... */
+ *size = MAX(*size, (wide_separators ? separator_width : style->xthickness));
+
+ return MOZ_GTK_SUCCESS;
+}
+
+gint
+moz_gtk_get_expander_size(gint* size)
+{
+ ensure_expander_widget();
+ gtk_widget_style_get(gExpanderWidget,
+ "expander-size", size,
+ NULL);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+gint
+moz_gtk_get_treeview_expander_size(gint* size)
+{
+ ensure_tree_view_widget();
+ gtk_widget_style_get(gTreeViewWidget,
+ "expander-size", size,
+ NULL);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+gint
+moz_gtk_get_menu_separator_height(gint *size)
+{
+ gboolean wide_separators = FALSE;
+ gint separator_height = 0;
+
+ ensure_menu_separator_widget();
+
+ if (have_2_10)
+ gtk_widget_style_get(gMenuSeparatorWidget,
+ "wide-separators", &wide_separators,
+ "separator-height", &separator_height,
+ NULL);
+
+ if (wide_separators)
+ *size = separator_height + gMenuSeparatorWidget->style->ythickness;
+ else
+ *size = gMenuSeparatorWidget->style->ythickness * 2;
+
+ return MOZ_GTK_SUCCESS;
+}
+
+gint
+moz_gtk_get_scalethumb_metrics(GtkOrientation orient, gint* thumb_length, gint* thumb_height)
+{
+ GtkWidget* widget;
+
+ ensure_scale_widget();
+ widget = ((orient == GTK_ORIENTATION_HORIZONTAL) ? gHScaleWidget : gVScaleWidget);
+
+ gtk_widget_style_get (widget,
+ "slider_length", thumb_length,
+ "slider_width", thumb_height,
+ NULL);
+
+ return MOZ_GTK_SUCCESS;
+}
+
+gint
+moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics *metrics)
+{
+ ensure_scrollbar_widget();
+
+ gtk_widget_style_get (gHorizScrollbarWidget,
+ "slider_width", &metrics->slider_width,
+ "trough_border", &metrics->trough_border,
+ "stepper_size", &metrics->stepper_size,
+ "stepper_spacing", &metrics->stepper_spacing,
+ NULL);
+
+ metrics->min_slider_size =
+ GTK_RANGE(gHorizScrollbarWidget)->min_slider_size;
+
+ return MOZ_GTK_SUCCESS;
+}
+
+gboolean
+moz_gtk_images_in_menus()
+{
+ gboolean result;
+ GtkSettings* settings;
+
+ ensure_image_menu_item_widget();
+ settings = gtk_widget_get_settings(gImageMenuItemWidget);
+
+ g_object_get(settings, "gtk-menu-images", &result, NULL);
+ return result;
+}
+
+gint
+moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable,
+ GdkRectangle* rect, GdkRectangle* cliprect,
+ GtkWidgetState* state, gint flags,
+ GtkTextDirection direction)
+{
+ switch (widget) {
+ case MOZ_GTK_BUTTON:
+ if (state->depressed) {
+ ensure_toggle_button_widget();
+ return moz_gtk_button_paint(drawable, rect, cliprect, state,
+ (GtkReliefStyle) flags,
+ gToggleButtonWidget, direction);
+ }
+ ensure_button_widget();
+ return moz_gtk_button_paint(drawable, rect, cliprect, state,
+ (GtkReliefStyle) flags, gButtonWidget,
+ direction);
+ break;
+ case MOZ_GTK_CHECKBUTTON:
+ case MOZ_GTK_RADIOBUTTON:
+ return moz_gtk_toggle_paint(drawable, rect, cliprect, state,
+ (gboolean) flags,
+ (widget == MOZ_GTK_RADIOBUTTON),
+ direction);
+ break;
+ case MOZ_GTK_SCROLLBAR_BUTTON:
+ return moz_gtk_scrollbar_button_paint(drawable, rect, cliprect, state,
+ (GtkScrollbarButtonFlags) flags,
+ direction);
+ break;
+ case MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL:
+ case MOZ_GTK_SCROLLBAR_TRACK_VERTICAL:
+ return moz_gtk_scrollbar_trough_paint(widget, drawable, rect,
+ cliprect, state, direction);
+ break;
+ case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL:
+ case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL:
+ return moz_gtk_scrollbar_thumb_paint(widget, drawable, rect,
+ cliprect, state, direction);
+ break;
+ case MOZ_GTK_SCALE_HORIZONTAL:
+ case MOZ_GTK_SCALE_VERTICAL:
+ return moz_gtk_scale_paint(drawable, rect, cliprect, state,
+ (GtkOrientation) flags, direction);
+ break;
+ case MOZ_GTK_SCALE_THUMB_HORIZONTAL:
+ case MOZ_GTK_SCALE_THUMB_VERTICAL:
+ return moz_gtk_scale_thumb_paint(drawable, rect, cliprect, state,
+ (GtkOrientation) flags, direction);
+ break;
+ case MOZ_GTK_SPINBUTTON:
+ return moz_gtk_spin_paint(drawable, rect, direction);
+ break;
+ case MOZ_GTK_SPINBUTTON_UP:
+ case MOZ_GTK_SPINBUTTON_DOWN:
+ return moz_gtk_spin_updown_paint(drawable, rect,
+ (widget == MOZ_GTK_SPINBUTTON_DOWN),
+ state, direction);
+ break;
+ case MOZ_GTK_SPINBUTTON_ENTRY:
+ ensure_spin_widget();
+ return moz_gtk_entry_paint(drawable, rect, cliprect, state,
+ gSpinWidget, direction);
+ break;
+ case MOZ_GTK_GRIPPER:
+ return moz_gtk_gripper_paint(drawable, rect, cliprect, state,
+ direction);
+ break;
+ case MOZ_GTK_TREEVIEW:
+ return moz_gtk_treeview_paint(drawable, rect, cliprect, state,
+ direction);
+ break;
+ case MOZ_GTK_TREE_HEADER_CELL:
+ return moz_gtk_tree_header_cell_paint(drawable, rect, cliprect, state,
+ flags, direction);
+ break;
+ case MOZ_GTK_TREE_HEADER_SORTARROW:
+ return moz_gtk_tree_header_sort_arrow_paint(drawable, rect, cliprect,
+ state,
+ (GtkArrowType) flags,
+ direction);
+ break;
+ case MOZ_GTK_TREEVIEW_EXPANDER:
+ return moz_gtk_treeview_expander_paint(drawable, rect, cliprect, state,
+ (GtkExpanderStyle) flags, direction);
+ break;
+ case MOZ_GTK_EXPANDER:
+ return moz_gtk_expander_paint(drawable, rect, cliprect, state,
+ (GtkExpanderStyle) flags, direction);
+ break;
+ case MOZ_GTK_ENTRY:
+ ensure_entry_widget();
+ return moz_gtk_entry_paint(drawable, rect, cliprect, state,
+ gEntryWidget, direction);
+ break;
+ case MOZ_GTK_ENTRY_CARET:
+ return moz_gtk_caret_paint(drawable, rect, cliprect, direction);
+ break;
+ case MOZ_GTK_DROPDOWN:
+ return moz_gtk_combo_box_paint(drawable, rect, cliprect, state,
+ (gboolean) flags, direction);
+ break;
+ case MOZ_GTK_DROPDOWN_ARROW:
+ return moz_gtk_combo_box_entry_button_paint(drawable, rect, cliprect,
+ state, flags, direction);
+ break;
+ case MOZ_GTK_DROPDOWN_ENTRY:
+ ensure_combo_box_entry_widgets();
+ return moz_gtk_entry_paint(drawable, rect, cliprect, state,
+ gComboBoxEntryTextareaWidget, direction);
+ break;
+ case MOZ_GTK_CHECKBUTTON_CONTAINER:
+ case MOZ_GTK_RADIOBUTTON_CONTAINER:
+ return moz_gtk_container_paint(drawable, rect, cliprect, state,
+ (widget == MOZ_GTK_RADIOBUTTON_CONTAINER),
+ direction);
+ break;
+ case MOZ_GTK_CHECKBUTTON_LABEL:
+ case MOZ_GTK_RADIOBUTTON_LABEL:
+ return moz_gtk_toggle_label_paint(drawable, rect, cliprect, state,
+ (widget == MOZ_GTK_RADIOBUTTON_LABEL),
+ direction);
+ break;
+ case MOZ_GTK_TOOLBAR:
+ return moz_gtk_toolbar_paint(drawable, rect, cliprect, direction);
+ break;
+ case MOZ_GTK_TOOLBAR_SEPARATOR:
+ return moz_gtk_toolbar_separator_paint(drawable, rect, cliprect,
+ direction);
+ break;
+ case MOZ_GTK_TOOLTIP:
+ return moz_gtk_tooltip_paint(drawable, rect, cliprect, direction);
+ break;
+ case MOZ_GTK_FRAME:
+ return moz_gtk_frame_paint(drawable, rect, cliprect, direction);
+ break;
+ case MOZ_GTK_RESIZER:
+ return moz_gtk_resizer_paint(drawable, rect, cliprect, state,
+ direction);
+ break;
+ case MOZ_GTK_PROGRESSBAR:
+ return moz_gtk_progressbar_paint(drawable, rect, cliprect, direction);
+ break;
+ case MOZ_GTK_PROGRESS_CHUNK:
+ return moz_gtk_progress_chunk_paint(drawable, rect, cliprect,
+ direction);
+ break;
+ case MOZ_GTK_TAB:
+ return moz_gtk_tab_paint(drawable, rect, cliprect,
+ (GtkTabFlags) flags, direction);
+ break;
+ case MOZ_GTK_TABPANELS:
+ return moz_gtk_tabpanels_paint(drawable, rect, cliprect, direction);
+ break;
+ case MOZ_GTK_TAB_SCROLLARROW:
+ return moz_gtk_tab_scroll_arrow_paint(drawable, rect, cliprect, state,
+ (GtkArrowType) flags, direction);
+ break;
+ case MOZ_GTK_MENUBAR:
+ return moz_gtk_menu_bar_paint(drawable, rect, cliprect, direction);
+ break;
+ case MOZ_GTK_MENUPOPUP:
+ return moz_gtk_menu_popup_paint(drawable, rect, cliprect, direction);
+ break;
+ case MOZ_GTK_MENUSEPARATOR:
+ return moz_gtk_menu_separator_paint(drawable, rect, cliprect,
+ direction);
+ break;
+ case MOZ_GTK_MENUITEM:
+ return moz_gtk_menu_item_paint(drawable, rect, cliprect, state, flags,
+ direction);
+ break;
+ case MOZ_GTK_MENUARROW:
+ return moz_gtk_menu_arrow_paint(drawable, rect, cliprect, state,
+ direction);
+ break;
+ case MOZ_GTK_TOOLBARBUTTON_ARROW:
+ return moz_gtk_downarrow_paint(drawable, rect, cliprect, state);
+ break;
+ case MOZ_GTK_CHECKMENUITEM:
+ case MOZ_GTK_RADIOMENUITEM:
+ return moz_gtk_check_menu_item_paint(drawable, rect, cliprect, state,
+ (gboolean) flags,
+ (widget == MOZ_GTK_RADIOMENUITEM),
+ direction);
+ break;
+ case MOZ_GTK_SPLITTER_HORIZONTAL:
+ return moz_gtk_vpaned_paint(drawable, rect, cliprect, state);
+ break;
+ case MOZ_GTK_SPLITTER_VERTICAL:
+ return moz_gtk_hpaned_paint(drawable, rect, cliprect, state);
+ break;
+ case MOZ_GTK_WINDOW:
+ return moz_gtk_window_paint(drawable, rect, cliprect, direction);
+ break;
+ default:
+ g_warning("Unknown widget type: %d", widget);
+ }
+
+ return MOZ_GTK_UNKNOWN_WIDGET;
+}
+
+GtkWidget* moz_gtk_get_scrollbar_widget(void)
+{
+ if (!is_initialized)
+ return NULL;
+ ensure_scrollbar_widget();
+ return gHorizScrollbarWidget;
+}
+
+gint
+moz_gtk_shutdown()
+{
+ GtkWidgetClass *entry_class;
+
+ if (gTooltipWidget)
+ gtk_widget_destroy(gTooltipWidget);
+ /* This will destroy all of our widgets */
+ if (gProtoWindow)
+ gtk_widget_destroy(gProtoWindow);
+
+ gProtoWindow = NULL;
+ gButtonWidget = NULL;
+ gToggleButtonWidget = NULL;
+ gButtonArrowWidget = NULL;
+ gCheckboxWidget = NULL;
+ gRadiobuttonWidget = NULL;
+ gHorizScrollbarWidget = NULL;
+ gVertScrollbarWidget = NULL;
+ gSpinWidget = NULL;
+ gHScaleWidget = NULL;
+ gVScaleWidget = NULL;
+ gEntryWidget = NULL;
+ gComboBoxWidget = NULL;
+ gComboBoxButtonWidget = NULL;
+ gComboBoxSeparatorWidget = NULL;
+ gComboBoxArrowWidget = NULL;
+ gComboBoxEntryWidget = NULL;
+ gComboBoxEntryButtonWidget = NULL;
+ gComboBoxEntryArrowWidget = NULL;
+ gComboBoxEntryTextareaWidget = NULL;
+ gHandleBoxWidget = NULL;
+ gToolbarWidget = NULL;
+ gStatusbarWidget = NULL;
+ gFrameWidget = NULL;
+ gProgressWidget = NULL;
+ gTabWidget = NULL;
+ gTooltipWidget = NULL;
+ gMenuBarWidget = NULL;
+ gMenuBarItemWidget = NULL;
+ gMenuPopupWidget = NULL;
+ gMenuItemWidget = NULL;
+ gImageMenuItemWidget = NULL;
+ gCheckMenuItemWidget = NULL;
+ gTreeViewWidget = NULL;
+ gMiddleTreeViewColumn = NULL;
+ gTreeHeaderCellWidget = NULL;
+ gTreeHeaderSortArrowWidget = NULL;
+ gExpanderWidget = NULL;
+ gToolbarSeparatorWidget = NULL;
+ gMenuSeparatorWidget = NULL;
+ gHPanedWidget = NULL;
+ gVPanedWidget = NULL;
+ gScrolledWindowWidget = NULL;
+
+ entry_class = g_type_class_peek(GTK_TYPE_ENTRY);
+ g_type_class_unref(entry_class);
+
+ is_initialized = FALSE;
+
+ return MOZ_GTK_SUCCESS;
+}
diff --git a/WebCore/platform/gtk/gtkdrawing.h b/WebCore/platform/gtk/gtkdrawing.h
new file mode 100644
index 0000000..6e44d4a
--- /dev/null
+++ b/WebCore/platform/gtk/gtkdrawing.h
@@ -0,0 +1,428 @@
+/* -*- 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) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brian Ryner <bryner@brianryner.com> (Original Author)
+ *
+ * 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 ***** */
+
+/**
+ * gtkdrawing.h: GTK widget rendering utilities
+ *
+ * gtkdrawing provides an API for rendering GTK widgets in the
+ * current theme to a pixmap or window, without requiring an actual
+ * widget instantiation, similar to the Macintosh Appearance Manager
+ * or Windows XP's DrawThemeBackground() API.
+ */
+
+#ifndef _GTK_DRAWING_H_
+#define _GTK_DRAWING_H_
+
+#include <gdk/gdk.h>
+#include <gtk/gtkstyle.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*** type definitions ***/
+typedef struct {
+ guint8 active;
+ guint8 focused;
+ guint8 inHover;
+ guint8 disabled;
+ guint8 isDefault;
+ guint8 canDefault;
+ /* The depressed state is for buttons which remain active for a longer period:
+ * activated toggle buttons or buttons showing a popup menu. */
+ guint8 depressed;
+ gint32 curpos; /* curpos and maxpos are used for scrollbars */
+ gint32 maxpos;
+} GtkWidgetState;
+
+typedef struct {
+ gint slider_width;
+ gint trough_border;
+ gint stepper_size;
+ gint stepper_spacing;
+ gint min_slider_size;
+} MozGtkScrollbarMetrics;
+
+typedef enum {
+ MOZ_GTK_STEPPER_DOWN = 1 << 0,
+ MOZ_GTK_STEPPER_BOTTOM = 1 << 1,
+ MOZ_GTK_STEPPER_VERTICAL = 1 << 2
+} GtkScrollbarButtonFlags;
+
+/** flags for tab state **/
+typedef enum {
+ /* first eight bits are used to pass a margin */
+ MOZ_GTK_TAB_MARGIN_MASK = 0xFF,
+ /* bottom tabs */
+ MOZ_GTK_TAB_BOTTOM = 1 << 8,
+ /* the first tab in the group */
+ MOZ_GTK_TAB_FIRST = 1 << 9,
+ /* the selected tab */
+ MOZ_GTK_TAB_SELECTED = 1 << 10
+} GtkTabFlags;
+
+/** flags for menuitems **/
+typedef enum {
+ /* menuitem is part of the menubar */
+ MOZ_TOPLEVEL_MENU_ITEM = 1 << 0
+} GtkMenuItemFlags;
+
+/* function type for moz_gtk_enable_style_props */
+typedef gint (*style_prop_t)(GtkStyle*, const gchar*, gint);
+
+/*** result/error codes ***/
+#define MOZ_GTK_SUCCESS 0
+#define MOZ_GTK_UNKNOWN_WIDGET -1
+#define MOZ_GTK_UNSAFE_THEME -2
+
+/*** widget type constants ***/
+typedef enum {
+ /* Paints a GtkButton. flags is a GtkReliefStyle. */
+ MOZ_GTK_BUTTON,
+ /* Paints a GtkCheckButton. flags is a boolean, 1=checked, 0=not checked. */
+ MOZ_GTK_CHECKBUTTON,
+ /* Paints a GtkRadioButton. flags is a boolean, 1=checked, 0=not checked. */
+ MOZ_GTK_RADIOBUTTON,
+ /**
+ * Paints the button of a GtkScrollbar. flags is a GtkArrowType giving
+ * the arrow direction.
+ */
+ MOZ_GTK_SCROLLBAR_BUTTON,
+ /* Paints the trough (track) of a GtkScrollbar. */
+ MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL,
+ MOZ_GTK_SCROLLBAR_TRACK_VERTICAL,
+ /* Paints the slider (thumb) of a GtkScrollbar. */
+ MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL,
+ MOZ_GTK_SCROLLBAR_THUMB_VERTICAL,
+ /* Paints a GtkScale. */
+ MOZ_GTK_SCALE_HORIZONTAL,
+ MOZ_GTK_SCALE_VERTICAL,
+ /* Paints a GtkScale thumb. */
+ MOZ_GTK_SCALE_THUMB_HORIZONTAL,
+ MOZ_GTK_SCALE_THUMB_VERTICAL,
+ /* Paints a GtkSpinButton */
+ MOZ_GTK_SPINBUTTON,
+ MOZ_GTK_SPINBUTTON_UP,
+ MOZ_GTK_SPINBUTTON_DOWN,
+ MOZ_GTK_SPINBUTTON_ENTRY,
+ /* Paints the gripper of a GtkHandleBox. */
+ MOZ_GTK_GRIPPER,
+ /* Paints a GtkEntry. */
+ MOZ_GTK_ENTRY,
+ /* Paints the native caret (or in GTK-speak: insertion cursor) */
+ MOZ_GTK_ENTRY_CARET,
+ /* Paints a GtkOptionMenu. */
+ MOZ_GTK_DROPDOWN,
+ /* Paints a dropdown arrow (a GtkButton containing a down GtkArrow). */
+ MOZ_GTK_DROPDOWN_ARROW,
+ /* Paints an entry in an editable option menu */
+ MOZ_GTK_DROPDOWN_ENTRY,
+ /* Paints the container part of a GtkCheckButton. */
+ MOZ_GTK_CHECKBUTTON_CONTAINER,
+ /* Paints the container part of a GtkRadioButton. */
+ MOZ_GTK_RADIOBUTTON_CONTAINER,
+ /* Paints the label of a GtkCheckButton (focus outline) */
+ MOZ_GTK_CHECKBUTTON_LABEL,
+ /* Paints the label of a GtkRadioButton (focus outline) */
+ MOZ_GTK_RADIOBUTTON_LABEL,
+ /* Paints the background of a GtkHandleBox. */
+ MOZ_GTK_TOOLBAR,
+ /* Paints a toolbar separator */
+ MOZ_GTK_TOOLBAR_SEPARATOR,
+ /* Paints a GtkToolTip */
+ MOZ_GTK_TOOLTIP,
+ /* Paints a GtkFrame (e.g. a status bar panel). */
+ MOZ_GTK_FRAME,
+ /* Paints a resize grip for a GtkWindow */
+ MOZ_GTK_RESIZER,
+ /* Paints a GtkProgressBar. */
+ MOZ_GTK_PROGRESSBAR,
+ /* Paints a progress chunk of a GtkProgressBar. */
+ MOZ_GTK_PROGRESS_CHUNK,
+ /* Paints a tab of a GtkNotebook. flags is a GtkTabFlags, defined above. */
+ MOZ_GTK_TAB,
+ /* Paints the background and border of a GtkNotebook. */
+ MOZ_GTK_TABPANELS,
+ /* Paints a GtkArrow for a GtkNotebook. flags is a GtkArrowType. */
+ MOZ_GTK_TAB_SCROLLARROW,
+ /* Paints the background and border of a GtkTreeView */
+ MOZ_GTK_TREEVIEW,
+ /* Paints treeheader cells */
+ MOZ_GTK_TREE_HEADER_CELL,
+ /* Paints sort arrows in treeheader cells */
+ MOZ_GTK_TREE_HEADER_SORTARROW,
+ /* Paints an expander for a GtkTreeView */
+ MOZ_GTK_TREEVIEW_EXPANDER,
+ /* Paints a GtkExpander */
+ MOZ_GTK_EXPANDER,
+ /* Paints the background of the menu bar. */
+ MOZ_GTK_MENUBAR,
+ /* Paints the background of menus, context menus. */
+ MOZ_GTK_MENUPOPUP,
+ /* Paints the arrow of menuitems that contain submenus */
+ MOZ_GTK_MENUARROW,
+ /* Paints an arrow that points down */
+ MOZ_GTK_TOOLBARBUTTON_ARROW,
+ /* Paints items of menubar and popups. */
+ MOZ_GTK_MENUITEM,
+ MOZ_GTK_CHECKMENUITEM,
+ MOZ_GTK_RADIOMENUITEM,
+ MOZ_GTK_MENUSEPARATOR,
+ /* Paints a GtkVPaned separator */
+ MOZ_GTK_SPLITTER_HORIZONTAL,
+ /* Paints a GtkHPaned separator */
+ MOZ_GTK_SPLITTER_VERTICAL,
+ /* Paints the background of a window, dialog or page. */
+ MOZ_GTK_WINDOW
+} GtkThemeWidgetType;
+
+/*** General library functions ***/
+/**
+ * Initializes the drawing library. You must call this function
+ * prior to using any other functionality.
+ * returns: MOZ_GTK_SUCCESS if there were no errors
+ * MOZ_GTK_UNSAFE_THEME if the current theme engine is known
+ * to crash with gtkdrawing.
+ */
+gint moz_gtk_init();
+
+/**
+ * Enable GTK+ 1.2.9+ theme enhancements. You must provide a pointer
+ * to the GTK+ 1.2.9+ function "gtk_style_get_prop_experimental".
+ * styleGetProp: pointer to gtk_style_get_prop_experimental
+ *
+ * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
+ */
+gint moz_gtk_enable_style_props(style_prop_t styleGetProp);
+
+/**
+ * Perform cleanup of the drawing library. You should call this function
+ * when your program exits, or you no longer need the library.
+ *
+ * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
+ */
+gint moz_gtk_shutdown();
+
+
+/*** Widget drawing ***/
+/**
+ * Paint a widget in the current theme.
+ * widget: a constant giving the widget to paint
+ * rect: the bounding rectangle for the widget
+ * cliprect: a clipprect rectangle for this painting operation
+ * state: the state of the widget. ignored for some widgets.
+ * flags: widget-dependant flags; see the GtkThemeWidgetType definition.
+ * direction: the text direction, to draw the widget correctly LTR and RTL.
+ */
+gint
+moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable,
+ GdkRectangle* rect, GdkRectangle* cliprect,
+ GtkWidgetState* state, gint flags,
+ GtkTextDirection direction);
+
+
+/*** Widget metrics ***/
+/**
+ * Get the border size of a widget
+ * left/right: [OUT] the widget's left/right border
+ * top/bottom: [OUT] the widget's top/bottom border
+ * direction: the text direction for the widget
+ * inhtml: boolean indicating whether this widget will be drawn as a HTML form control,
+ * in order to workaround a size issue (MOZ_GTK_BUTTON only, ignored otherwise)
+ *
+ * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
+ */
+gint moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
+ gint* right, gint* bottom, GtkTextDirection direction,
+ gboolean inhtml);
+
+/**
+ * Get the desired size of a GtkCheckButton
+ * indicator_size: [OUT] the indicator size
+ * indicator_spacing: [OUT] the spacing between the indicator and its
+ * container
+ *
+ * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
+ */
+gint
+moz_gtk_checkbox_get_metrics(gint* indicator_size, gint* indicator_spacing);
+
+/**
+ * Get the desired size of a GtkRadioButton
+ * indicator_size: [OUT] the indicator size
+ * indicator_spacing: [OUT] the spacing between the indicator and its
+ * container
+ *
+ * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
+ */
+gint
+moz_gtk_radio_get_metrics(gint* indicator_size, gint* indicator_spacing);
+
+/**
+ * Get the inner-border value for a GtkButton widget (button or tree header)
+ * widget: [IN] the widget to get the border value for
+ * inner_border: [OUT] the inner border
+ *
+ * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
+ */
+gint
+moz_gtk_button_get_inner_border(GtkWidget* widget, GtkBorder* inner_border);
+
+/** Get the focus metrics for a treeheadercell, button, checkbox, or radio button.
+ * widget: [IN] the widget to get the focus metrics for
+ * interior_focus: [OUT] whether the focus is drawn around the
+ * label (TRUE) or around the whole container (FALSE)
+ * focus_width: [OUT] the width of the focus line
+ * focus_pad: [OUT] the padding between the focus line and children
+ *
+ * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
+ */
+gint
+moz_gtk_widget_get_focus(GtkWidget* widget, gboolean* interior_focus,
+ gint* focus_width, gint* focus_pad);
+
+/**
+ * Get the desired size of a GtkScale thumb
+ * orient: [IN] the scale orientation
+ * thumb_length: [OUT] the length of the thumb
+ * thumb_height: [OUT] the height of the thumb
+ *
+ * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
+ */
+gint
+moz_gtk_get_scalethumb_metrics(GtkOrientation orient, gint* thumb_length, gint* thumb_height);
+
+/**
+ * Get the desired metrics for a GtkScrollbar
+ * metrics: [IN] struct which will contain the metrics
+ *
+ * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
+ */
+gint
+moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics* metrics);
+
+/**
+ * Get the desired size of a dropdown arrow button
+ * width: [OUT] the desired width
+ * height: [OUT] the desired height
+ *
+ * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
+ */
+gint moz_gtk_get_combo_box_entry_button_size(gint* width, gint* height);
+
+/**
+ * Get the desired size of a scroll arrow widget
+ * width: [OUT] the desired width
+ * height: [OUT] the desired height
+ *
+ * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
+ */
+gint moz_gtk_get_tab_scroll_arrow_size(gint* width, gint* height);
+
+/**
+ * Get the desired size of a toolbar button dropdown arrow
+ * width: [OUT] the desired width
+ * height: [OUT] the desired height
+ *
+ * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
+ */
+gint moz_gtk_get_downarrow_size(gint* width, gint* height);
+
+/**
+ * Get the desired size of a toolbar separator
+ * size: [OUT] the desired width
+ *
+ * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
+ */
+gint moz_gtk_get_toolbar_separator_width(gint* size);
+
+/**
+ * Get the size of a regular GTK expander that shows/hides content
+ * size: [OUT] the size of the GTK expander, size = width = height.
+ *
+ * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
+ */
+gint moz_gtk_get_expander_size(gint* size);
+
+/**
+ * Get the size of a treeview's expander (we call them twisties)
+ * size: [OUT] the size of the GTK expander, size = width = height.
+ *
+ * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
+ */
+gint moz_gtk_get_treeview_expander_size(gint* size);
+
+/**
+ * Get the desired height of a menu separator
+ * size: [OUT] the desired height
+ *
+ * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
+ */
+gint moz_gtk_get_menu_separator_height(gint* size);
+
+/**
+ * Get the desired size of a splitter
+ * orientation: [IN] GTK_ORIENTATION_HORIZONTAL or GTK_ORIENTATION_VERTICAL
+ * size: [OUT] width or height of the splitter handle
+ *
+ * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
+ */
+gint moz_gtk_splitter_get_metrics(gint orientation, gint* size);
+
+/**
+ * Retrieve an actual GTK scrollbar widget for style analysis. It will not
+ * be modified.
+ */
+GtkWidget* moz_gtk_get_scrollbar_widget(void);
+
+/**
+ * Get the YTHICKNESS of a tab (notebook extension).
+ */
+gint moz_gtk_get_tab_thickness(void);
+
+/**
+ * Get a boolean which indicates whether or not to use images in menus.
+ * If TRUE, use images in menus.
+ */
+gboolean moz_gtk_images_in_menus(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/WebCore/platform/gtk/guriescape.c b/WebCore/platform/gtk/guriescape.c
new file mode 100644
index 0000000..0792587
--- /dev/null
+++ b/WebCore/platform/gtk/guriescape.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2008 Collabora, Ltd.
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ * Copyright (C) 1997-2000 The GLib Team
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "guriescape.h"
+
+#include <string.h>
+
+#if !PLATFORM(WIN_OS) && !GLIB_CHECK_VERSION(2,16,0)
+
+/* is_valid, gunichar_ok and g_string_append_uri_escaped were copied for glib/gstring.c
+ * in the glib package.
+ *
+ * Original copyright:
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * Modified by the GLib Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GLib Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
+ *
+ * Please don't change the indentation so it's easier to update these functions
+ * if they are changed in glib.
+ */
+static gboolean
+is_valid (char c, const char *reserved_chars_allowed)
+{
+ if (g_ascii_isalnum (c) ||
+ c == '-' ||
+ c == '.' ||
+ c == '_' ||
+ c == '~')
+ return TRUE;
+
+ if (reserved_chars_allowed &&
+ strchr (reserved_chars_allowed, c) != NULL)
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean
+gunichar_ok (gunichar c)
+{
+ return
+ (c != (gunichar) -2) &&
+ (c != (gunichar) -1);
+}
+
+static GString *
+_webcore_g_string_append_uri_escaped (GString *string,
+ const char *unescaped,
+ const char *reserved_chars_allowed,
+ gboolean allow_utf8)
+{
+ unsigned char c;
+ const char *end;
+ static const gchar hex[16] = "0123456789ABCDEF";
+
+ g_return_val_if_fail (string != NULL, NULL);
+ g_return_val_if_fail (unescaped != NULL, NULL);
+
+ end = unescaped + strlen (unescaped);
+
+ while ((c = *unescaped) != 0)
+ {
+ if (c >= 0x80 && allow_utf8 &&
+ gunichar_ok (g_utf8_get_char_validated (unescaped, end - unescaped)))
+ {
+ int len = g_utf8_skip [c];
+ g_string_append_len (string, unescaped, len);
+ unescaped += len;
+ }
+ else if (is_valid (c, reserved_chars_allowed))
+ {
+ g_string_append_c (string, c);
+ unescaped++;
+ }
+ else
+ {
+ g_string_append_c (string, '%');
+ g_string_append_c (string, hex[((guchar)c) >> 4]);
+ g_string_append_c (string, hex[((guchar)c) & 0xf]);
+ unescaped++;
+ }
+ }
+
+ return string;
+}
+
+/* g_uri_escape_string, unescape_character, g_uri_unescape_segment and
+ * g_uri_unescape_string were copied for glib/gurifuncs.c in the glib package
+ * and prefixed with _webcore (if necessary) to avoid exporting a symbol with
+ * the "g_" prefix.
+ *
+ * Original copyright:
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ * Author: Alexander Larsson <alexl@redhat.com>
+ *
+ * Please don't change the indentation so it's easier to update this function
+ * if it's changed in glib.
+ */
+char *
+_webcore_g_uri_escape_string (const char *unescaped,
+ const char *reserved_chars_allowed,
+ gboolean allow_utf8)
+{
+ GString *s;
+
+ g_return_val_if_fail (unescaped != NULL, NULL);
+
+ s = g_string_sized_new (strlen (unescaped) + 10);
+
+ _webcore_g_string_append_uri_escaped (s, unescaped, reserved_chars_allowed, allow_utf8);
+
+ return g_string_free (s, FALSE);
+}
+
+static int
+unescape_character (const char *scanner)
+{
+ int first_digit;
+ int second_digit;
+
+ first_digit = g_ascii_xdigit_value (*scanner++);
+ if (first_digit < 0)
+ return -1;
+
+ second_digit = g_ascii_xdigit_value (*scanner++);
+ if (second_digit < 0)
+ return -1;
+
+ return (first_digit << 4) | second_digit;
+}
+
+
+
+static char *
+_webcore_g_uri_unescape_segment (const char *escaped_string,
+ const char *escaped_string_end,
+ const char *illegal_characters)
+{
+ const char *in;
+ char *out, *result;
+ gint character;
+
+ if (escaped_string == NULL)
+ return NULL;
+
+ if (escaped_string_end == NULL)
+ escaped_string_end = escaped_string + strlen (escaped_string);
+
+ result = g_malloc (escaped_string_end - escaped_string + 1);
+
+ out = result;
+ for (in = escaped_string; in < escaped_string_end; in++)
+ {
+ character = *in;
+
+ if (*in == '%')
+ {
+ in++;
+
+ if (escaped_string_end - in < 2)
+ {
+ /* Invalid escaped char (to short) */
+ g_free (result);
+ return NULL;
+ }
+
+ character = unescape_character (in);
+
+ /* Check for an illegal character. We consider '\0' illegal here. */
+ if (character <= 0 ||
+ (illegal_characters != NULL &&
+ strchr (illegal_characters, (char)character) != NULL))
+ {
+ g_free (result);
+ return NULL;
+ }
+
+ in++; /* The other char will be eaten in the loop header */
+ }
+ *out++ = (char)character;
+ }
+
+ *out = '\0';
+
+ return result;
+}
+
+
+char *
+_webcore_g_uri_unescape_string (const char *escaped_string,
+ const char *illegal_characters)
+{
+ return _webcore_g_uri_unescape_segment (escaped_string, NULL, illegal_characters);
+}
+
+#endif /* #if !PLATFORM(WIN_OS) && !GLIB_CHECK_VERSION(2,16,0) */
diff --git a/WebCore/platform/gtk/guriescape.h b/WebCore/platform/gtk/guriescape.h
new file mode 100644
index 0000000..8c6662a
--- /dev/null
+++ b/WebCore/platform/gtk/guriescape.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2008 Collabora, Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef guriescape_h
+#define guriescape_h
+
+#include <glib.h>
+#include <wtf/Platform.h>
+
+G_BEGIN_DECLS
+
+#if !PLATFORM(WIN_OS) && !GLIB_CHECK_VERSION(2,16,0)
+
+#define g_uri_escape_string _webcore_g_uri_escape_string
+#define g_uri_unescape_string _webcore_g_uri_unescape_string
+
+char *_webcore_g_uri_escape_string (const char *unescaped,
+ const char *reserved_chars_allowed,
+ gboolean allow_utf8);
+
+char *_webcore_g_uri_unescape_string (const char *escaped_string,
+ const char *illegal_characters);
+
+#endif
+
+G_END_DECLS
+
+#endif /* guriescape_h */