summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/gtk
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/gtk')
-rw-r--r--WebCore/platform/gtk/ClipboardGtk.cpp3
-rw-r--r--WebCore/platform/gtk/ClipboardGtk.h13
-rw-r--r--WebCore/platform/gtk/CursorGtk.cpp69
-rw-r--r--WebCore/platform/gtk/DragDataGtk.cpp3
-rw-r--r--WebCore/platform/gtk/EventLoopGtk.cpp32
-rw-r--r--WebCore/platform/gtk/FileChooserGtk.cpp61
-rw-r--r--WebCore/platform/gtk/FileSystemGtk.cpp128
-rw-r--r--WebCore/platform/gtk/KURLGtk.cpp (renamed from WebCore/platform/gtk/CookieJarGtk.cpp)34
-rw-r--r--WebCore/platform/gtk/KeyEventGtk.cpp55
-rw-r--r--WebCore/platform/gtk/Language.cpp24
-rw-r--r--WebCore/platform/gtk/LocalizedStringsGtk.cpp57
-rw-r--r--WebCore/platform/gtk/MIMETypeRegistryGtk.cpp3
-rw-r--r--WebCore/platform/gtk/MouseEventGtk.cpp9
-rw-r--r--WebCore/platform/gtk/PasteboardGtk.cpp6
-rw-r--r--WebCore/platform/gtk/PlatformScreenGtk.cpp94
-rw-r--r--WebCore/platform/gtk/PopupMenuGtk.cpp28
-rw-r--r--WebCore/platform/gtk/RenderThemeGtk.cpp73
-rw-r--r--WebCore/platform/gtk/RenderThemeGtk.h3
-rw-r--r--WebCore/platform/gtk/ScrollViewGtk.cpp805
-rw-r--r--WebCore/platform/gtk/ScrollbarGtk.cpp (renamed from WebCore/platform/gtk/PlatformScrollBarGtk.cpp)104
-rw-r--r--WebCore/platform/gtk/ScrollbarGtk.h (renamed from WebCore/platform/gtk/PlatformScrollBar.h)41
-rw-r--r--WebCore/platform/gtk/ScrollbarThemeGtk.cpp56
-rw-r--r--WebCore/platform/gtk/ScrollbarThemeGtk.h41
-rw-r--r--WebCore/platform/gtk/SearchPopupMenuGtk.cpp2
-rw-r--r--WebCore/platform/gtk/SharedBufferGtk.cpp53
-rw-r--r--WebCore/platform/gtk/SharedTimerGtk.cpp2
-rw-r--r--WebCore/platform/gtk/TemporaryLinkStubs.cpp27
-rw-r--r--WebCore/platform/gtk/ThreadingGtk.cpp209
-rw-r--r--WebCore/platform/gtk/WheelEventGtk.cpp15
-rw-r--r--WebCore/platform/gtk/WidgetGtk.cpp212
-rw-r--r--WebCore/platform/gtk/gtk2drawing.c1176
-rw-r--r--WebCore/platform/gtk/gtkdrawing.h40
-rw-r--r--WebCore/platform/gtk/guriescape.c219
-rw-r--r--WebCore/platform/gtk/guriescape.h44
34 files changed, 2046 insertions, 1695 deletions
diff --git a/WebCore/platform/gtk/ClipboardGtk.cpp b/WebCore/platform/gtk/ClipboardGtk.cpp
index 12e3a01..44aa7f7 100644
--- a/WebCore/platform/gtk/ClipboardGtk.cpp
+++ b/WebCore/platform/gtk/ClipboardGtk.cpp
@@ -23,9 +23,10 @@
#include "Editor.h"
namespace WebCore {
+
PassRefPtr<Clipboard> Editor::newGeneralClipboard(ClipboardAccessPolicy policy)
{
- return new ClipboardGtk(policy, false);
+ return ClipboardGtk::create(policy, false);
}
ClipboardGtk::ClipboardGtk(ClipboardAccessPolicy policy, bool forDragging)
diff --git a/WebCore/platform/gtk/ClipboardGtk.h b/WebCore/platform/gtk/ClipboardGtk.h
index 3ad1049..b8b4ddf 100644
--- a/WebCore/platform/gtk/ClipboardGtk.h
+++ b/WebCore/platform/gtk/ClipboardGtk.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * 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
@@ -36,9 +36,11 @@ namespace WebCore {
// Created from the EventHandlerGtk to be used by the dom
class ClipboardGtk : public Clipboard {
public:
- ClipboardGtk(ClipboardAccessPolicy, bool);
- ~ClipboardGtk();
-
+ static PassRefPtr<ClipboardGtk> create(ClipboardAccessPolicy policy, bool isForDragging)
+ {
+ return adoptRef(new ClipboardGtk(policy, isForDragging));
+ }
+ virtual ~ClipboardGtk();
void clearData(const String&);
void clearAllData();
@@ -58,6 +60,9 @@ namespace WebCore {
virtual void writeRange(Range*, Frame*);
virtual bool hasData();
+
+ private:
+ ClipboardGtk(ClipboardAccessPolicy, bool);
};
}
diff --git a/WebCore/platform/gtk/CursorGtk.cpp b/WebCore/platform/gtk/CursorGtk.cpp
index 94c6975..76f6d00 100644
--- a/WebCore/platform/gtk/CursorGtk.cpp
+++ b/WebCore/platform/gtk/CursorGtk.cpp
@@ -28,7 +28,6 @@
#include "config.h"
#include "CursorGtk.h"
-#include "DeprecatedString.h"
#include "NotImplemented.h"
#include <wtf/Assertions.h>
@@ -214,6 +213,52 @@ 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()
{
@@ -223,7 +268,7 @@ const Cursor& verticalTextCursor()
const Cursor& cellCursor()
{
- // TODO: Find a suitable cursor
+ notImplemented();
return pointerCursor();
}
@@ -235,7 +280,7 @@ const Cursor& contextMenuCursor()
const Cursor& noDropCursor()
{
- // TODO: Find a suitable cursor
+ notImplemented();
return pointerCursor();
}
@@ -247,7 +292,7 @@ const Cursor& copyCursor()
const Cursor& progressCursor()
{
- // TODO: Find a suitable cursor
+ notImplemented();
return pointerCursor();
}
@@ -259,13 +304,13 @@ const Cursor& aliasCursor()
const Cursor& noneCursor()
{
- // TODO: Find a suitable cursor
+ notImplemented();
return pointerCursor();
}
const Cursor& notAllowedCursor()
{
- // TODO: Find a suitable cursor
+ notImplemented();
return pointerCursor();
}
@@ -281,4 +326,16 @@ const Cursor& zoomOutCursor()
return c;
}
+const Cursor& grabCursor()
+{
+ notImplemented();
+ return pointerCursor();
+}
+
+const Cursor& grabbingCursor()
+{
+ notImplemented();
+ return pointerCursor();
+}
+
}
diff --git a/WebCore/platform/gtk/DragDataGtk.cpp b/WebCore/platform/gtk/DragDataGtk.cpp
index e20a1bf..69b3161 100644
--- a/WebCore/platform/gtk/DragDataGtk.cpp
+++ b/WebCore/platform/gtk/DragDataGtk.cpp
@@ -17,6 +17,7 @@
#include "config.h"
#include "DragData.h"
+#include "Clipboard.h"
#include "Document.h"
#include "DocumentFragment.h"
@@ -56,7 +57,7 @@ Color DragData::asColor() const
return Color();
}
-Clipboard* DragData::createClipboard(ClipboardAccessPolicy) const
+PassRefPtr<Clipboard> DragData::createClipboard(ClipboardAccessPolicy) const
{
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
index c41a693..e984718 100644
--- a/WebCore/platform/gtk/FileChooserGtk.cpp
+++ b/WebCore/platform/gtk/FileChooserGtk.cpp
@@ -28,8 +28,7 @@
#include "FileChooser.h"
#include "CString.h"
-#include "Document.h"
-#include "FrameView.h"
+#include "FileSystem.h"
#include "Icon.h"
#include "LocalizedStrings.h"
#include "StringTruncator.h"
@@ -45,52 +44,12 @@ static bool stringByAdoptingFileSystemRepresentation(gchar* systemFilename, Stri
if (!systemFilename)
return false;
- gchar* filename = g_filename_to_utf8(systemFilename, -1, 0, 0, 0);
+ result = filenameToString(systemFilename);
g_free(systemFilename);
- if (!filename)
- return false;
-
- result = String::fromUTF8(filename);
- g_free(filename);
return true;
}
-FileChooser::FileChooser(FileChooserClient* client, const String& filename)
- : m_client(client)
- , m_filename(filename)
- , m_icon(chooseIcon(filename))
-{
-}
-
-FileChooser::~FileChooser()
-{
-}
-
-void FileChooser::openFileChooser(Document* document)
-{
- FrameView* view = document->view();
- if (!view)
- return;
-
- GtkWidget* dialog = gtk_file_chooser_dialog_new(_("Upload File"),
- GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view->containingWindow()))),
- GTK_FILE_CHOOSER_ACTION_OPEN,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
- NULL);
-
- // We need this protector because otherwise we can be deleted if the file upload control is detached while
- // we're within the gtk_run_dialog call.
- RefPtr<FileChooser> protector(this);
- String result;
-
- const bool acceptedDialog = gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT;
- if (acceptedDialog && stringByAdoptingFileSystemRepresentation(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)), result))
- chooseFile(result);
- gtk_widget_destroy(dialog);
-}
-
String FileChooser::basenameForWidth(const Font& font, int width) const
{
if (width <= 0)
@@ -98,15 +57,13 @@ String FileChooser::basenameForWidth(const Font& font, int width) const
String string = fileButtonNoFileSelectedLabel();
- if (!m_filename.isEmpty()) {
- gchar* systemFilename = g_filename_from_utf8(m_filename.utf8().data(), -1, 0, 0, 0);
- if (systemFilename) {
- gchar* systemBasename = g_path_get_basename(systemFilename);
- g_free(systemFilename);
-
- stringByAdoptingFileSystemRepresentation(systemBasename, string);
- }
- }
+ 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
index 904fe9f..965cea9 100644
--- a/WebCore/platform/gtk/FileSystemGtk.cpp
+++ b/WebCore/platform/gtk/FileSystemGtk.cpp
@@ -22,6 +22,7 @@
#include "config.h"
#include "FileSystem.h"
+#include "guriescape.h"
#include "NotImplemented.h"
#include "PlatformString.h"
#include "CString.h"
@@ -30,12 +31,61 @@
#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 = g_filename_from_utf8(path.utf8().data(), -1, 0, 0, 0);
+ gchar* filename = filenameFromString(path);
if (filename) {
result = g_file_test(filename, G_FILE_TEST_EXISTS);
@@ -48,7 +98,7 @@ bool fileExists(const String& path)
bool deleteFile(const String& path)
{
bool result = false;
- gchar* filename = g_filename_from_utf8(path.utf8().data(), -1, 0, 0, 0);
+ gchar* filename = filenameFromString(path);
if (filename) {
result = g_remove(filename) == 0;
@@ -61,7 +111,7 @@ bool deleteFile(const String& path)
bool deleteEmptyDirectory(const String& path)
{
bool result = false;
- gchar* filename = g_filename_from_utf8(path.utf8().data(), -1, 0, 0, 0);
+ gchar* filename = filenameFromString(path);
if (filename) {
result = g_rmdir(filename) == 0;
@@ -73,7 +123,7 @@ bool deleteEmptyDirectory(const String& path)
bool getFileSize(const String& path, long long& resultSize)
{
- gchar* filename = g_filename_from_utf8(path.utf8().data(), -1, 0, 0, 0);
+ gchar* filename = filenameFromString(path);
if (!filename)
return false;
@@ -87,10 +137,21 @@ bool getFileSize(const String& path, long long& resultSize)
return true;
}
-bool getFileModificationTime(const String&, time_t&)
+bool getFileModificationTime(const String& path, time_t& modifiedTime)
{
- notImplemented();
- return false;
+ 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)
@@ -103,7 +164,7 @@ String pathByAppendingComponent(const String& path, const String& component)
bool makeAllDirectories(const String& path)
{
- gchar* filename = g_filename_from_utf8(path.utf8().data(), -1, 0, 0, 0);
+ gchar* filename = filenameFromString(path);
if (!filename)
return false;
@@ -113,6 +174,52 @@ bool makeAllDirectories(const String& path)
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);
@@ -152,4 +259,9 @@ int writeToFile(PlatformFileHandle handle, const char* data, int length)
return totalBytesWritten;
}
+
+bool unloadModule(PlatformModule module)
+{
+ return g_module_close(module);
+}
}
diff --git a/WebCore/platform/gtk/CookieJarGtk.cpp b/WebCore/platform/gtk/KURLGtk.cpp
index 2813a2e..4858d3e 100644
--- a/WebCore/platform/gtk/CookieJarGtk.cpp
+++ b/WebCore/platform/gtk/KURLGtk.cpp
@@ -1,4 +1,6 @@
/*
+ * 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
@@ -15,32 +17,24 @@
*/
#include "config.h"
-#include "CookieJar.h"
-
-#include "DeprecatedString.h"
#include "KURL.h"
-#include "PlatformString.h"
-#include "StringHash.h"
-#include <wtf/HashMap.h>
+#include "CString.h"
+#include "FileSystem.h"
-namespace WebCore {
+#include <glib.h>
-static HashMap<String, String> cookieJar;
-
-void setCookies(Document* /*document*/, const KURL& url, const KURL& /*policyURL*/, const String& value)
-{
- cookieJar.set(url.string(), value);
-}
+namespace WebCore {
-String cookies(const Document* /*document*/, const KURL& url)
+String KURL::fileSystemPath() const
{
- return cookieJar.get(url.string());
-}
+ gchar* filename = g_filename_from_uri(m_string.utf8().data(), 0, 0);
+ if (!filename)
+ return String();
-bool cookiesEnabled(const Document* /*document*/)
-{
- return true;
+ 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
index 5d2efcf..153ef19 100644
--- a/WebCore/platform/gtk/KeyEventGtk.cpp
+++ b/WebCore/platform/gtk/KeyEventGtk.cpp
@@ -2,6 +2,7 @@
* 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
@@ -29,13 +30,13 @@
#include "config.h"
#include "PlatformKeyboardEvent.h"
-#include "DeprecatedString.h"
#include "KeyboardCodes.h"
#include "NotImplemented.h"
#include "TextEncoding.h"
#include <gdk/gdk.h>
#include <gdk/gdkkeysyms.h>
+#include <gtk/gtkversion.h>
namespace WebCore {
@@ -187,6 +188,8 @@ static int windowsKeyCodeForKeyEvent(unsigned int keycode)
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:
@@ -469,21 +472,30 @@ static int windowsKeyCodeForKeyEvent(unsigned int keycode)
static String singleCharacterString(guint val)
{
- glong nwc;
- String retVal;
- gunichar c = gdk_keyval_to_unicode(val);
- gunichar2* uchar16 = g_ucs4_to_utf16(&c, 1, 0, &nwc, 0);
+ 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);
- if (uchar16)
- retVal = String((UChar*)uchar16, nwc);
- else
- retVal = String();
+ String retVal;
+ if (uchar16)
+ retVal = String((UChar*)uchar16, nwc);
+ else
+ retVal = String();
- g_free(uchar16);
+ g_free(uchar16);
- return retVal;
+ 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))
@@ -491,20 +503,30 @@ PlatformKeyboardEvent::PlatformKeyboardEvent(GdkEventKey* event)
, m_keyIdentifier(keyIdentifierForGdkKeyCode(event->keyval))
, m_autoRepeat(false)
, m_windowsVirtualKeyCode(windowsKeyCodeForKeyEvent(event->keyval))
- , m_isKeypad(false)
+ , 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)
- , m_metaKey(event->state & GDK_MOD2_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)
+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();
@@ -520,4 +542,9 @@ bool PlatformKeyboardEvent::currentCapsLockState()
return false;
}
+GdkEventKey* PlatformKeyboardEvent::gdkEventKey() const
+{
+ return m_gdkEventKey;
+}
+
}
diff --git a/WebCore/platform/gtk/Language.cpp b/WebCore/platform/gtk/Language.cpp
index 171cd84..6ae7305 100644
--- a/WebCore/platform/gtk/Language.cpp
+++ b/WebCore/platform/gtk/Language.cpp
@@ -26,6 +26,30 @@
#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()
diff --git a/WebCore/platform/gtk/LocalizedStringsGtk.cpp b/WebCore/platform/gtk/LocalizedStringsGtk.cpp
index 041cd83..52d4f5f 100644
--- a/WebCore/platform/gtk/LocalizedStringsGtk.cpp
+++ b/WebCore/platform/gtk/LocalizedStringsGtk.cpp
@@ -3,7 +3,7 @@
* Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
* Copyright (C) 2007 Holger Hans Peter Freyther
* Copyright (C) 2008 Christian Dywan <christian@imendio.com>
- * All rights reserved.
+ * Copyright (C) 2008 Nuanti Ltd.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,6 +30,7 @@
#include "config.h"
#include "LocalizedStrings.h"
+#include "NotImplemented.h"
#include "PlatformString.h"
#include <gtk/gtk.h>
@@ -124,7 +125,7 @@ String contextMenuItemTagDelete()
String contextMenuItemTagSelectAll()
{
-#if GLIB_CHECK_VERSION(2,10,0)
+#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"));
@@ -285,9 +286,61 @@ 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/MIMETypeRegistryGtk.cpp b/WebCore/platform/gtk/MIMETypeRegistryGtk.cpp
index c7c90ad..20fe0cb 100644
--- a/WebCore/platform/gtk/MIMETypeRegistryGtk.cpp
+++ b/WebCore/platform/gtk/MIMETypeRegistryGtk.cpp
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2006 Zack Rusin <zack@kde.org>
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
- * Copyright (C) 2007 Trolltech ASA
+ * 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
@@ -37,6 +37,7 @@ struct ExtensionMap {
static const ExtensionMap extensionMap [] = {
{ "bmp", "image/bmp" },
+ { "css", "text/css" },
{ "gif", "image/gif" },
{ "html", "text/html" },
{ "ico", "image/x-icon" },
diff --git a/WebCore/platform/gtk/MouseEventGtk.cpp b/WebCore/platform/gtk/MouseEventGtk.cpp
index 29ea371..f441f00 100644
--- a/WebCore/platform/gtk/MouseEventGtk.cpp
+++ b/WebCore/platform/gtk/MouseEventGtk.cpp
@@ -31,11 +31,13 @@
#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;
@@ -44,7 +46,12 @@ PlatformMouseEvent::PlatformMouseEvent(GdkEventButton* event)
m_shiftKey = event->state & GDK_SHIFT_MASK;
m_ctrlKey = event->state & GDK_CONTROL_MASK;
m_altKey = event->state & GDK_MOD1_MASK;
- m_metaKey = event->state & GDK_MOD2_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:
diff --git a/WebCore/platform/gtk/PasteboardGtk.cpp b/WebCore/platform/gtk/PasteboardGtk.cpp
index 745728c..15a7e64 100644
--- a/WebCore/platform/gtk/PasteboardGtk.cpp
+++ b/WebCore/platform/gtk/PasteboardGtk.cpp
@@ -102,16 +102,20 @@ void Pasteboard::setHelper(PasteboardHelper* 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);
- GtkClipboard* clipboard = m_helper->getClipboard(frame);
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)
diff --git a/WebCore/platform/gtk/PlatformScreenGtk.cpp b/WebCore/platform/gtk/PlatformScreenGtk.cpp
index 74c785f..9788253 100644
--- a/WebCore/platform/gtk/PlatformScreenGtk.cpp
+++ b/WebCore/platform/gtk/PlatformScreenGtk.cpp
@@ -1,6 +1,8 @@
/*
* 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
@@ -28,44 +30,104 @@
#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)
{
- ASSERT(widget->containingWindow() && GTK_WIDGET(widget->containingWindow())->window);
+ GtkWidget* container = GTK_WIDGET(widget->root()->hostWindow()->platformWindow());
+ if (!container)
+ return 24;
- gint dummy, depth;
- gdk_window_get_geometry(GTK_WIDGET(widget->containingWindow())->window, &dummy, &dummy, &dummy, &dummy, &depth);
- return depth;
+ GdkVisual* visual = gdk_drawable_get_visual(GDK_DRAWABLE(GTK_WIDGET(widget->root()->hostWindow()->platformWindow())->window));
+ return visual->depth;
}
-int screenDepthPerComponent(Widget*)
+int screenDepthPerComponent(Widget* widget)
{
- notImplemented();
- return 8;
+ 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*)
+bool screenIsMonochrome(Widget* widget)
{
- notImplemented();
- return false;
+ GtkWidget* container = GTK_WIDGET(widget->root()->hostWindow()->platformWindow());
+ if (!container)
+ return false;
+
+ return screenDepth(widget) < 2;
}
-FloatRect screenRect(Widget*)
+FloatRect screenRect(Widget* widget)
{
- notImplemented();
- return FloatRect();
+ 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*)
+FloatRect screenAvailableRect(Widget* widget)
{
- notImplemented();
- return FloatRect();
+#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
index b4689f6..85c5aa0 100644
--- a/WebCore/platform/gtk/PopupMenuGtk.cpp
+++ b/WebCore/platform/gtk/PopupMenuGtk.cpp
@@ -1,8 +1,9 @@
/*
* This file is part of the popup menu implementation for <select> elements in WebCore.
*
- * Copyright (C) 2006, 2007 Apple Inc.
+ * 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
@@ -26,6 +27,7 @@
#include "CString.h"
#include "FrameView.h"
+#include "HostWindow.h"
#include "NotImplemented.h"
#include "PlatformString.h"
#include <gtk/gtk.h>
@@ -61,7 +63,7 @@ void PopupMenu::show(const IntRect& rect, FrameView* view, int index)
gtk_container_foreach(GTK_CONTAINER(m_popup), reinterpret_cast<GtkCallback>(menuRemoveItem), this);
int x, y;
- gdk_window_get_origin(GTK_WIDGET(view->containingWindow())->window, &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();
@@ -77,7 +79,7 @@ void PopupMenu::show(const IntRect& rect, FrameView* view, int index)
m_indexMap.add(item, i);
g_signal_connect(item, "activate", G_CALLBACK(menuItemActivated), this);
- // FIXME: Apply the RenderStyle from client()->itemStyle(i)
+ // 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);
@@ -91,6 +93,24 @@ void PopupMenu::show(const IntRect& rect, FrameView* view, int index)
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());
}
@@ -127,7 +147,7 @@ void PopupMenu::menuPositionFunction(GtkMenu*, gint* x, gint* y, gboolean* pushI
{
*x = that->m_menuPosition.x();
*y = that->m_menuPosition.y();
- pushIn = false;
+ *pushIn = true;
}
void PopupMenu::menuRemoveItem(GtkWidget* widget, PopupMenu* that)
diff --git a/WebCore/platform/gtk/RenderThemeGtk.cpp b/WebCore/platform/gtk/RenderThemeGtk.cpp
index 0113b9e..bf8b8d7 100644
--- a/WebCore/platform/gtk/RenderThemeGtk.cpp
+++ b/WebCore/platform/gtk/RenderThemeGtk.cpp
@@ -1,6 +1,7 @@
/*
* 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
@@ -20,9 +21,12 @@
*/
#include "config.h"
+#include "RenderThemeGtk.h"
+
+#include "AffineTransform.h"
+#include "GraphicsContext.h"
#include "NotImplemented.h"
#include "RenderObject.h"
-#include "RenderThemeGtk.h"
#include "gtkdrawing.h"
#include <gdk/gdk.h>
@@ -35,25 +39,31 @@ RenderTheme* theme()
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(EAppearance appearance)
+static bool supportsFocus(ControlPart appearance)
{
switch (appearance) {
- case PushButtonAppearance:
- case ButtonAppearance:
- case TextFieldAppearance:
- case TextAreaAppearance:
- case SearchFieldAppearance:
- case MenulistAppearance:
- case RadioAppearance:
- case CheckboxAppearance:
+ case PushButtonPart:
+ case ButtonPart:
+ case TextFieldPart:
+ case TextAreaPart:
+ case SearchFieldPart:
+ case MenulistPart:
+ case RadioPart:
+ case CheckboxPart:
return true;
default:
return false;
@@ -70,11 +80,11 @@ bool RenderThemeGtk::controlSupportsTints(const RenderObject* o) const
return isEnabled(o);
}
-short RenderThemeGtk::baselinePosition(const RenderObject* o) const
+int RenderThemeGtk::baselinePosition(const RenderObject* o) const
{
// FIXME: This strategy is possibly incorrect for the GTK+ port.
- if (o->style()->appearance() == CheckboxAppearance ||
- o->style()->appearance() == RadioAppearance)
+ if (o->style()->appearance() == CheckboxPart ||
+ o->style()->appearance() == RadioPart)
return o->marginTop() + o->height() - 2;
return RenderTheme::baselinePosition(o);
}
@@ -151,12 +161,31 @@ static bool paintMozWidget(RenderTheme* theme, GtkThemeWidgetType type, RenderOb
break;
}
- IntPoint pos = i.context->translatePoint(rect.location());
+ 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());
- // FIXME: Pass the real clip region.
- return moz_gtk_widget_paint(type, i.context->gdkDrawable(), &gdkRect, &gdkRect, &mozState, flags, direction) != MOZ_GTK_SUCCESS;
+#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)
@@ -169,7 +198,7 @@ static void setButtonPadding(RenderStyle* style)
style->setPaddingBottom(Length(padding / 2, Fixed));
}
-static void setToggleSize(RenderStyle* style, EAppearance appearance)
+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())
@@ -179,11 +208,11 @@ static void setToggleSize(RenderStyle* style, EAppearance appearance)
gint indicator_size, indicator_spacing;
switch (appearance) {
- case CheckboxAppearance:
+ case CheckboxPart:
if (moz_gtk_checkbox_get_metrics(&indicator_size, &indicator_spacing) != MOZ_GTK_SUCCESS)
return;
break;
- case RadioAppearance:
+ case RadioPart:
if (moz_gtk_radio_get_metrics(&indicator_size, &indicator_spacing) != MOZ_GTK_SUCCESS)
return;
break;
@@ -203,7 +232,7 @@ static void setToggleSize(RenderStyle* style, EAppearance appearance)
void RenderThemeGtk::setCheckboxSize(RenderStyle* style) const
{
- setToggleSize(style, RadioAppearance);
+ setToggleSize(style, RadioPart);
}
bool RenderThemeGtk::paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
@@ -213,7 +242,7 @@ bool RenderThemeGtk::paintCheckbox(RenderObject* o, const RenderObject::PaintInf
void RenderThemeGtk::setRadioSize(RenderStyle* style) const
{
- setToggleSize(style, RadioAppearance);
+ setToggleSize(style, RadioPart);
}
bool RenderThemeGtk::paintRadio(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
@@ -224,7 +253,7 @@ bool RenderThemeGtk::paintRadio(RenderObject* o, const RenderObject::PaintInfo&
void RenderThemeGtk::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, WebCore::Element* e) const
{
// FIXME: Is this condition necessary?
- if (style->appearance() == PushButtonAppearance) {
+ if (style->appearance() == PushButtonPart) {
style->resetBorder();
style->setHeight(Length(Auto));
style->setWhiteSpace(PRE);
diff --git a/WebCore/platform/gtk/RenderThemeGtk.h b/WebCore/platform/gtk/RenderThemeGtk.h
index b908793..dda8bc8 100644
--- a/WebCore/platform/gtk/RenderThemeGtk.h
+++ b/WebCore/platform/gtk/RenderThemeGtk.h
@@ -28,7 +28,6 @@
#define RenderThemeGdk_h
#include "RenderTheme.h"
-#include "GraphicsContext.h"
#include <gtk/gtk.h>
@@ -53,7 +52,7 @@ public:
// 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 short baselinePosition(const RenderObject*) const;
+ virtual int baselinePosition(const RenderObject*) const;
// The platform selection color.
virtual Color platformActiveSelectionBackgroundColor() const;
diff --git a/WebCore/platform/gtk/ScrollViewGtk.cpp b/WebCore/platform/gtk/ScrollViewGtk.cpp
index ec43128..e1316ee 100644
--- a/WebCore/platform/gtk/ScrollViewGtk.cpp
+++ b/WebCore/platform/gtk/ScrollViewGtk.cpp
@@ -1,7 +1,8 @@
/*
- * Copyright (C) 2006, 2007 Apple Computer, Inc. All rights reserved.
+ * 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.
*
@@ -31,17 +32,14 @@
#include "ScrollView.h"
#include "FloatRect.h"
-#include "FocusController.h"
-#include "Frame.h"
-#include "FrameView.h"
#include "GraphicsContext.h"
+#include "HostWindow.h"
#include "IntRect.h"
#include "NotImplemented.h"
#include "PlatformMouseEvent.h"
#include "PlatformWheelEvent.h"
-#include "PlatformScrollBar.h"
-#include "Page.h"
-#include "RenderLayer.h"
+#include "ScrollbarGtk.h"
+#include "ScrollbarTheme.h"
#include <gtk/gtk.h>
@@ -49,213 +47,45 @@ using namespace std;
namespace WebCore {
-class ScrollViewScrollbar : public PlatformScrollbar {
-public:
- ScrollViewScrollbar(ScrollbarClient*, ScrollbarOrientation, ScrollbarControlSize);
-
-protected:
- void geometryChanged();
-};
-
-class ScrollView::ScrollViewPrivate : public ScrollbarClient
-{
-public:
- ScrollViewPrivate(ScrollView* _view)
- : view(_view)
- , hasStaticBackground(false)
- , scrollbarsSuppressed(false)
- , vScrollbarMode(ScrollbarAuto)
- , hScrollbarMode(ScrollbarAuto)
- , inUpdateScrollbars(false)
- , horizontalAdjustment(0)
- , verticalAdjustment(0)
- {}
-
- ~ScrollViewPrivate()
- {
- setHasHorizontalScrollbar(false);
- setHasVerticalScrollbar(false);
-
- if (horizontalAdjustment) {
- g_signal_handlers_disconnect_by_func(G_OBJECT(horizontalAdjustment), (gpointer)ScrollViewPrivate::adjustmentChanged, this);
- g_object_unref(horizontalAdjustment);
- }
-
- if (verticalAdjustment) {
- g_signal_handlers_disconnect_by_func(G_OBJECT(verticalAdjustment), (gpointer)ScrollViewPrivate::adjustmentChanged, this);
- g_object_unref(verticalAdjustment);
- }
- }
-
- void scrollBackingStore(const IntSize& scrollDelta);
-
- void setHasHorizontalScrollbar(bool hasBar);
- void setHasVerticalScrollbar(bool hasBar);
-
- virtual void valueChanged(Scrollbar*);
- virtual IntRect windowClipRect() const;
- virtual bool isActive() const;
-
- static void adjustmentChanged(GtkAdjustment*, gpointer);
-
- ScrollView* view;
- bool hasStaticBackground;
- bool scrollbarsSuppressed;
- ScrollbarMode vScrollbarMode;
- ScrollbarMode hScrollbarMode;
- RefPtr<ScrollViewScrollbar> vBar;
- RefPtr<ScrollViewScrollbar> hBar;
- IntSize scrollOffset;
- IntSize contentsSize;
- IntSize viewPortSize;
- bool inUpdateScrollbars;
- HashSet<Widget*> children;
- GtkAdjustment* horizontalAdjustment;
- GtkAdjustment* verticalAdjustment;
-};
-
-ScrollViewScrollbar::ScrollViewScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize size)
- : PlatformScrollbar(client, orientation, size)
-{
-}
-
-void ScrollViewScrollbar::geometryChanged()
-{
- if (!parent())
- return;
-
- ASSERT(parent()->isFrameView());
-
- FrameView* frameView = static_cast<FrameView*>(parent());
- IntPoint loc = frameView->convertToContainingWindow(frameGeometry().location());
-
- // Don't allow the allocation size to be negative
- IntSize sz = frameGeometry().size();
- sz.clampNegativeToZero();
-
- GtkAllocation allocation = { loc.x(), loc.y(), sz.width(), sz.height() };
- gtk_widget_size_allocate(gtkWidget(), &allocation);
-}
-
-void ScrollView::ScrollViewPrivate::setHasHorizontalScrollbar(bool hasBar)
-{
- if (Scrollbar::hasPlatformScrollbars()) {
- if (hasBar && !hBar && !horizontalAdjustment) {
- hBar = new ScrollViewScrollbar(this, HorizontalScrollbar, RegularScrollbar);
- view->addChild(hBar.get());
- } else if (!hasBar && hBar) {
- view->removeChild(hBar.get());
- hBar = 0;
- }
- }
-}
-
-void ScrollView::ScrollViewPrivate::setHasVerticalScrollbar(bool hasBar)
-{
- if (Scrollbar::hasPlatformScrollbars()) {
- if (hasBar && !vBar && !verticalAdjustment) {
- vBar = new ScrollViewScrollbar(this, VerticalScrollbar, RegularScrollbar);
- view->addChild(vBar.get());
- } else if (!hasBar && vBar) {
- view->removeChild(vBar.get());
- vBar = 0;
- }
- }
-}
-
-
-void ScrollView::ScrollViewPrivate::scrollBackingStore(const IntSize& scrollDelta)
-{
- // Since scrolling is double buffered, we will be blitting the scroll view's intersection
- // with the clip rect every time to keep it smooth.
- IntRect clipRect = view->windowClipRect();
- IntRect scrollViewRect = view->convertToContainingWindow(IntRect(0, 0, view->visibleWidth(), view->visibleHeight()));
-
- IntRect updateRect = clipRect;
- updateRect.intersect(scrollViewRect);
-
- //FIXME update here?
-
- if (!hasStaticBackground) // The main frame can just blit the WebView window
- // FIXME: Find a way to blit subframes without blitting overlapping content
- view->scrollBackingStore(-scrollDelta.width(), -scrollDelta.height(), scrollViewRect, clipRect);
- else {
- // We need to go ahead and repaint the entire backing store. Do it now before moving the
- // plugins.
- view->addToDirtyRegion(updateRect);
- view->updateBackingStore();
- }
-
- view->geometryChanged();
-
- // Now update the window (which should do nothing but a blit of the backing store's updateRect and so should
- // be very fast).
- view->update();
-}
-
-void ScrollView::ScrollViewPrivate::adjustmentChanged(GtkAdjustment* adjustment, gpointer _that)
+static void adjustmentChanged(GtkAdjustment* adjustment, gpointer _that)
{
- ScrollViewPrivate* that = reinterpret_cast<ScrollViewPrivate*>(_that);
+ ScrollView* that = reinterpret_cast<ScrollView*>(_that);
// Figure out if we really moved.
- IntSize newOffset = that->scrollOffset;
- if (adjustment == that->horizontalAdjustment)
+ IntSize newOffset = that->scrollOffset();
+ if (adjustment == that->m_horizontalAdjustment)
newOffset.setWidth(static_cast<int>(gtk_adjustment_get_value(adjustment)));
- else if (adjustment == that->verticalAdjustment)
+ else if (adjustment == that->m_verticalAdjustment)
newOffset.setHeight(static_cast<int>(gtk_adjustment_get_value(adjustment)));
- IntSize scrollDelta = newOffset - that->scrollOffset;
+ IntSize scrollDelta = newOffset - that->scrollOffset();
if (scrollDelta == IntSize())
return;
- that->scrollOffset = newOffset;
+ that->setScrollOffset(newOffset);
- if (that->scrollbarsSuppressed)
+ if (that->scrollbarsSuppressed())
return;
- that->scrollBackingStore(scrollDelta);
- static_cast<FrameView*>(that->view)->frame()->sendScrollEvent();
+ that->scrollContents(scrollDelta);
}
-void ScrollView::ScrollViewPrivate::valueChanged(Scrollbar* bar)
+void ScrollView::platformInit()
{
- // Figure out if we really moved.
- IntSize newOffset = scrollOffset;
- if (bar) {
- if (bar == hBar)
- newOffset.setWidth(bar->value());
- else if (bar == vBar)
- newOffset.setHeight(bar->value());
- }
- IntSize scrollDelta = newOffset - scrollOffset;
- if (scrollDelta == IntSize())
- return;
- scrollOffset = newOffset;
-
- if (scrollbarsSuppressed)
- return;
-
- scrollBackingStore(scrollDelta);
- static_cast<FrameView*>(view)->frame()->sendScrollEvent();
+ m_horizontalAdjustment = 0;
+ m_verticalAdjustment = 0;
}
-IntRect ScrollView::ScrollViewPrivate::windowClipRect() const
+void ScrollView::platformDestroy()
{
- return static_cast<const FrameView*>(view)->windowClipRect(false);
-}
-
-bool ScrollView::ScrollViewPrivate::isActive() const
-{
- Page* page = static_cast<const FrameView*>(view)->frame()->page();
- return page && page->focusController()->isActive();
-}
-
-ScrollView::ScrollView()
- : m_data(new ScrollViewPrivate(this))
-{}
+ if (m_horizontalAdjustment) {
+ g_signal_handlers_disconnect_by_func(G_OBJECT(m_horizontalAdjustment), (gpointer)adjustmentChanged, this);
+ g_object_unref(m_horizontalAdjustment);
+ }
-ScrollView::~ScrollView()
-{
- delete m_data;
+ if (m_verticalAdjustment) {
+ g_signal_handlers_disconnect_by_func(G_OBJECT(m_verticalAdjustment), (gpointer)adjustmentChanged, this);
+ g_object_unref(m_verticalAdjustment);
+ }
}
/*
@@ -266,567 +96,100 @@ void ScrollView::setGtkAdjustments(GtkAdjustment* hadj, GtkAdjustment* vadj)
{
ASSERT(!hadj == !vadj);
- if (m_data->horizontalAdjustment) {
- g_signal_handlers_disconnect_by_func(G_OBJECT(m_data->horizontalAdjustment), (gpointer)ScrollViewPrivate::adjustmentChanged, m_data);
- g_signal_handlers_disconnect_by_func(G_OBJECT(m_data->verticalAdjustment), (gpointer)ScrollViewPrivate::adjustmentChanged, m_data);
- g_object_unref(m_data->horizontalAdjustment);
- g_object_unref(m_data->verticalAdjustment);
+ 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_data->horizontalAdjustment = hadj;
- m_data->verticalAdjustment = vadj;
+ m_horizontalAdjustment = hadj;
+ m_verticalAdjustment = vadj;
- if (m_data->horizontalAdjustment) {
- g_signal_connect(m_data->horizontalAdjustment, "value-changed", G_CALLBACK(ScrollViewPrivate::adjustmentChanged), m_data);
- g_signal_connect(m_data->verticalAdjustment, "value-changed", G_CALLBACK(ScrollViewPrivate::adjustmentChanged), m_data);
+ 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
*/
- m_data->setHasVerticalScrollbar(false);
- m_data->setHasHorizontalScrollbar(false);
-
-#if GLIB_CHECK_VERSION(2,10,0)
- g_object_ref_sink(m_data->horizontalAdjustment);
- g_object_ref_sink(m_data->verticalAdjustment);
-#else
- g_object_ref(m_data->horizontalAdjustment);
- gtk_object_sink(GTK_OBJECT(m_data->horizontalAdjustment));
- g_object_ref(m_data->verticalAdjustment);
- gtk_object_sink(GTK_OBJECT(m_data->verticalAdjustment));
-#endif
- }
-
- updateScrollbars(m_data->scrollOffset);
-}
-
-void ScrollView::updateContents(const IntRect& updateRect, bool now)
-{
- if (updateRect.isEmpty())
- return;
-
- IntPoint windowPoint = contentsToWindow(updateRect.location());
- IntRect containingWindowRect = updateRect;
- containingWindowRect.setLocation(windowPoint);
-
- GdkRectangle rect = containingWindowRect;
- GdkWindow* window = GTK_WIDGET(containingWindow())->window;
-
- if (window)
- gdk_window_invalidate_rect(window, &rect, true);
-
- // Cache the dirty spot.
- addToDirtyRegion(containingWindowRect);
-
- if (now && window)
- gdk_window_process_updates(window, true);
-}
-
-void ScrollView::update()
-{
- ASSERT(containingWindow());
-
- GdkRectangle rect = frameGeometry();
- gdk_window_invalidate_rect(GTK_WIDGET(containingWindow())->window, &rect, true);
-}
-
-int ScrollView::visibleWidth() const
-{
- return width() - (m_data->vBar ? m_data->vBar->width() : 0);
-}
-
-int ScrollView::visibleHeight() const
-{
- return height() - (m_data->hBar ? m_data->hBar->height() : 0);
-}
-
-// Region of the content currently visible in the viewport in the content view's coordinate system.
-FloatRect ScrollView::visibleContentRect() const
-{
- return FloatRect(contentsX(), contentsY(), visibleWidth(), visibleHeight());
-}
-
-FloatRect ScrollView::visibleContentRectConsideringExternalScrollers() const
-{
- // external scrollers not supported for now
- return visibleContentRect();
-}
-
-void ScrollView::setContentsPos(int newX, int newY)
-{
- int dx = newX - contentsX();
- int dy = newY - contentsY();
- scrollBy(dx, dy);
-}
-
-void ScrollView::resizeContents(int w, int h)
-{
- IntSize newSize(w, h);
- if (m_data->contentsSize == newSize)
- return;
-
- m_data->contentsSize = newSize;
- updateScrollbars(m_data->scrollOffset);
-}
-
-int ScrollView::contentsX() const
-{
- return scrollOffset().width();
-}
-
-int ScrollView::contentsY() const
-{
- return scrollOffset().height();
-}
-
-int ScrollView::contentsWidth() const
-{
- return m_data->contentsSize.width();
-}
-
-int ScrollView::contentsHeight() const
-{
- return m_data->contentsSize.height();
-}
-
-IntSize ScrollView::scrollOffset() const
-{
- return m_data->scrollOffset;
-}
-
-IntSize ScrollView::maximumScroll() const
-{
- IntSize delta = (m_data->contentsSize - IntSize(visibleWidth(), visibleHeight())) - scrollOffset();
- delta.clampNegativeToZero();
- return delta;
-}
-
-void ScrollView::scrollBy(int dx, int dy)
-{
- IntSize scrollOffset = m_data->scrollOffset;
- IntSize newScrollOffset = scrollOffset + IntSize(dx, dy).shrunkTo(maximumScroll());
- newScrollOffset.clampNegativeToZero();
-
- if (newScrollOffset == scrollOffset)
- return;
-
- updateScrollbars(newScrollOffset);
-}
-
-ScrollbarMode ScrollView::hScrollbarMode() const
-{
- return m_data->hScrollbarMode;
-}
-
-ScrollbarMode ScrollView::vScrollbarMode() const
-{
- return m_data->vScrollbarMode;
-}
-
-void ScrollView::suppressScrollbars(bool suppressed, bool repaintOnSuppress)
-{
- m_data->scrollbarsSuppressed = suppressed;
- if (repaintOnSuppress)
- updateScrollbars(m_data->scrollOffset);
-}
-
-void ScrollView::setHScrollbarMode(ScrollbarMode newMode)
-{
- if (m_data->hScrollbarMode != newMode) {
- m_data->hScrollbarMode = newMode;
- updateScrollbars(m_data->scrollOffset);
- }
-}
-
-void ScrollView::setVScrollbarMode(ScrollbarMode newMode)
-{
- if (m_data->vScrollbarMode != newMode) {
- m_data->vScrollbarMode = newMode;
- updateScrollbars(m_data->scrollOffset);
- }
-}
-
-void ScrollView::setScrollbarsMode(ScrollbarMode newMode)
-{
- m_data->hScrollbarMode = m_data->vScrollbarMode = newMode;
- updateScrollbars(m_data->scrollOffset);
-}
-
-void ScrollView::setStaticBackground(bool flag)
-{
- m_data->hasStaticBackground = flag;
-}
-
-void ScrollView::setFrameGeometry(const IntRect& newGeometry)
-{
- ASSERT(isFrameView());
- IntRect oldGeometry = frameGeometry();
- Widget::setFrameGeometry(newGeometry);
+ setHasVerticalScrollbar(false);
+ setHasHorizontalScrollbar(false);
- if (newGeometry == oldGeometry)
- return;
- if (newGeometry.width() != oldGeometry.width() || newGeometry.height() != oldGeometry.height()) {
- updateScrollbars(m_data->scrollOffset);
- static_cast<FrameView*>(this)->setNeedsLayout();
+ g_object_ref(m_horizontalAdjustment);
+ g_object_ref(m_verticalAdjustment);
}
- geometryChanged();
+ updateScrollbars(m_scrollOffset);
}
-void ScrollView::addChild(Widget* child)
+void ScrollView::platformAddChild(Widget* child)
{
- child->setParent(this);
- child->setContainingWindow(containingWindow());
- m_data->children.add(child);
-
- if (child->gtkWidget())
- gtk_container_add(GTK_CONTAINER(containingWindow()), child->gtkWidget());
+ if (!GTK_IS_SOCKET(child->platformWidget()))
+ gtk_container_add(GTK_CONTAINER(hostWindow()->platformWindow()), child->platformWidget());
}
-void ScrollView::removeChild(Widget* child)
+void ScrollView::platformRemoveChild(Widget* child)
{
- child->setParent(0);
- m_data->children.remove(child);
+ GtkWidget* parent;
- if (child->gtkWidget() && GTK_WIDGET(containingWindow()) == GTK_WIDGET(child->gtkWidget())->parent)
- gtk_container_remove(GTK_CONTAINER(containingWindow()), child->gtkWidget());
-}
+ // 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);
-void ScrollView::scrollRectIntoViewRecursively(const IntRect& r)
-{
- IntPoint p(max(0, r.x()), max(0, r.y()));
- ScrollView* view = this;
- while (view) {
- view->setContentsPos(p.x(), p.y());
- p.move(view->x() - view->scrollOffset().width(), view->y() - view->scrollOffset().height());
- view = static_cast<ScrollView*>(view->parent());
- }
+ if (GTK_IS_CONTAINER(parent) && parent == child->platformWidget()->parent)
+ gtk_container_remove(GTK_CONTAINER(parent), child->platformWidget());
}
-bool ScrollView::inWindow() const
+bool ScrollView::platformHandleHorizontalAdjustment(const IntSize& scroll)
{
- notImplemented();
- return true;
-}
-
-void ScrollView::wheelEvent(PlatformWheelEvent& e)
-{
- // Determine how much we want to scroll. If we can move at all, we will accept the event.
- IntSize maxScrollDelta = maximumScroll();
- if ((e.deltaX() < 0 && maxScrollDelta.width() > 0) ||
- (e.deltaX() > 0 && scrollOffset().width() > 0) ||
- (e.deltaY() < 0 && maxScrollDelta.height() > 0) ||
- (e.deltaY() > 0 && scrollOffset().height() > 0))
- e.accept();
-
- scrollBy(-e.deltaX() * LINE_STEP, -e.deltaY() * LINE_STEP);
-}
-
-void ScrollView::updateScrollbars(const IntSize& desiredOffset)
-{
- // Don't allow re-entrancy into this function.
- if (m_data->inUpdateScrollbars)
- return;
-
- // FIXME: This code is here so we don't have to fork FrameView.h/.cpp.
- // In the end, FrameView should just merge with ScrollView.
- if (static_cast<const FrameView*>(this)->frame()->prohibitsScrolling())
- return;
-
- m_data->inUpdateScrollbars = true;
-
- bool hasVerticalScrollbar = m_data->vBar;
- bool hasHorizontalScrollbar = m_data->hBar;
- bool oldHasVertical = hasVerticalScrollbar;
- bool oldHasHorizontal = hasHorizontalScrollbar;
- ScrollbarMode hScroll = m_data->hScrollbarMode;
- ScrollbarMode vScroll = m_data->vScrollbarMode;
-
- const int cVerticalWidth = PlatformScrollbar::verticalScrollbarWidth();
- const int cHorizontalHeight = PlatformScrollbar::horizontalScrollbarHeight();
+ 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);
- for (int pass = 0; pass < 2; pass++) {
- bool scrollsVertically;
- bool scrollsHorizontally;
-
- if (!m_data->scrollbarsSuppressed && (hScroll == ScrollbarAuto || vScroll == ScrollbarAuto)) {
- // Do a layout if pending before checking if scrollbars are needed.
- if (hasVerticalScrollbar != oldHasVertical || hasHorizontalScrollbar != oldHasHorizontal)
- static_cast<FrameView*>(this)->layout();
-
- scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && contentsHeight() > height());
- if (scrollsVertically)
- scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() + cVerticalWidth > width());
- else {
- scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() > width());
- if (scrollsHorizontally)
- scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && contentsHeight() + cHorizontalHeight > height());
- }
- }
- else {
- scrollsHorizontally = (hScroll == ScrollbarAuto) ? hasHorizontalScrollbar : (hScroll == ScrollbarAlwaysOn);
- scrollsVertically = (vScroll == ScrollbarAuto) ? hasVerticalScrollbar : (vScroll == ScrollbarAlwaysOn);
- }
-
- if (hasVerticalScrollbar != scrollsVertically) {
- m_data->setHasVerticalScrollbar(scrollsVertically);
- hasVerticalScrollbar = scrollsVertically;
- }
-
- if (hasHorizontalScrollbar != scrollsHorizontally) {
- m_data->setHasHorizontalScrollbar(scrollsHorizontally);
- hasHorizontalScrollbar = scrollsHorizontally;
+ if (m_scrollOffset.width() != scroll.width()) {
+ m_horizontalAdjustment->value = scroll.width();
+ gtk_adjustment_value_changed(m_horizontalAdjustment);
}
+ return true;
}
-
- // Set up the range (and page step/line step).
- IntSize maxScrollPosition(contentsWidth() - visibleWidth(), contentsHeight() - visibleHeight());
- IntSize scroll = desiredOffset.shrunkTo(maxScrollPosition);
- scroll.clampNegativeToZero();
-
- if (m_data->horizontalAdjustment) {
- m_data->horizontalAdjustment->page_size = visibleWidth();
- m_data->horizontalAdjustment->step_increment = visibleWidth() / 10.0;
- m_data->horizontalAdjustment->page_increment = visibleWidth() * 0.9;
- m_data->horizontalAdjustment->lower = 0;
- m_data->horizontalAdjustment->upper = contentsWidth();
- gtk_adjustment_changed(m_data->horizontalAdjustment);
-
- if (m_data->scrollOffset.width() != scroll.width()) {
- m_data->horizontalAdjustment->value = scroll.width();
- gtk_adjustment_value_changed(m_data->horizontalAdjustment);
- }
- } else if (m_data->hBar) {
- int clientWidth = visibleWidth();
- m_data->hBar->setEnabled(contentsWidth() > clientWidth);
- int pageStep = (clientWidth - PAGE_KEEP);
- if (pageStep < 0) pageStep = clientWidth;
- IntRect oldRect(m_data->hBar->frameGeometry());
- IntRect hBarRect = IntRect(0,
- height() - m_data->hBar->height(),
- width() - (m_data->vBar ? m_data->vBar->width() : 0),
- m_data->hBar->height());
- m_data->hBar->setRect(hBarRect);
- if (!m_data->scrollbarsSuppressed && oldRect != m_data->hBar->frameGeometry())
- m_data->hBar->invalidate();
-
- if (m_data->scrollbarsSuppressed)
- m_data->hBar->setSuppressInvalidation(true);
- m_data->hBar->setSteps(LINE_STEP, pageStep);
- m_data->hBar->setProportion(clientWidth, contentsWidth());
- m_data->hBar->setValue(scroll.width());
- if (m_data->scrollbarsSuppressed)
- m_data->hBar->setSuppressInvalidation(false);
- }
-
- if (m_data->verticalAdjustment) {
- m_data->verticalAdjustment->page_size = visibleHeight();
- m_data->verticalAdjustment->step_increment = visibleHeight() / 10.0;
- m_data->verticalAdjustment->page_increment = visibleHeight() * 0.9;
- m_data->verticalAdjustment->lower = 0;
- m_data->verticalAdjustment->upper = contentsHeight();
- gtk_adjustment_changed(m_data->verticalAdjustment);
-
- if (m_data->scrollOffset.height() != scroll.height()) {
- m_data->verticalAdjustment->value = scroll.height();
- gtk_adjustment_value_changed(m_data->verticalAdjustment);
- }
- } else if (m_data->vBar) {
- int clientHeight = visibleHeight();
- m_data->vBar->setEnabled(contentsHeight() > clientHeight);
- int pageStep = (clientHeight - PAGE_KEEP);
- if (pageStep < 0) pageStep = clientHeight;
- IntRect oldRect(m_data->vBar->frameGeometry());
- IntRect vBarRect = IntRect(width() - m_data->vBar->width(),
- 0,
- m_data->vBar->width(),
- height() - (m_data->hBar ? m_data->hBar->height() : 0));
- m_data->vBar->setRect(vBarRect);
- if (!m_data->scrollbarsSuppressed && oldRect != m_data->vBar->frameGeometry())
- m_data->vBar->invalidate();
-
- if (m_data->scrollbarsSuppressed)
- m_data->vBar->setSuppressInvalidation(true);
- m_data->vBar->setSteps(LINE_STEP, pageStep);
- m_data->vBar->setProportion(clientHeight, contentsHeight());
- m_data->vBar->setValue(scroll.height());
- if (m_data->scrollbarsSuppressed)
- m_data->vBar->setSuppressInvalidation(false);
- }
-
- if (oldHasVertical != (m_data->vBar != 0) || oldHasHorizontal != (m_data->hBar != 0))
- geometryChanged();
-
- // See if our offset has changed in a situation where we might not have scrollbars.
- // This can happen when editing a body with overflow:hidden and scrolling to reveal selection.
- // It can also happen when maximizing a window that has scrollbars (but the new maximized result
- // does not).
- IntSize scrollDelta = scroll - m_data->scrollOffset;
- if (scrollDelta != IntSize()) {
- m_data->scrollOffset = scroll;
- m_data->scrollBackingStore(scrollDelta);
- }
-
- m_data->inUpdateScrollbars = false;
-}
-
-IntPoint ScrollView::windowToContents(const IntPoint& windowPoint) const
-{
- IntPoint viewPoint = convertFromContainingWindow(windowPoint);
- return viewPoint + scrollOffset();
-}
-
-IntPoint ScrollView::contentsToWindow(const IntPoint& contentsPoint) const
-{
- IntPoint viewPoint = contentsPoint - scrollOffset();
- return convertToContainingWindow(viewPoint);
-}
-
-PlatformScrollbar* ScrollView::scrollbarUnderMouse(const PlatformMouseEvent& mouseEvent)
-{
- IntPoint viewPoint = convertFromContainingWindow(mouseEvent.pos());
- if (m_data->hBar && m_data->hBar->frameGeometry().contains(viewPoint))
- return m_data->hBar.get();
- if (m_data->vBar && m_data->vBar->frameGeometry().contains(viewPoint))
- return m_data->vBar.get();
- return 0;
-}
-
-IntPoint ScrollView::convertChildToSelf(const Widget* child, const IntPoint& point) const
-{
- IntPoint newPoint = point;
- if (child != m_data->hBar && child != m_data->vBar)
- newPoint = point - scrollOffset();
- return Widget::convertChildToSelf(child, newPoint);
-}
-
-IntPoint ScrollView::convertSelfToChild(const Widget* child, const IntPoint& point) const
-{
- IntPoint newPoint = point;
- if (child != m_data->hBar && child != m_data->vBar)
- newPoint = point + scrollOffset();
- return Widget::convertSelfToChild(child, newPoint);
+ return false;
}
-void ScrollView::paint(GraphicsContext* context, const IntRect& rect)
+bool ScrollView::platformHandleVerticalAdjustment(const IntSize& scroll)
{
- // FIXME: This code is here so we don't have to fork FrameView.h/.cpp.
- // In the end, FrameView should just merge with ScrollView.
- ASSERT(isFrameView());
-
- if (context->paintingDisabled())
- return;
-
- IntRect documentDirtyRect = rect;
- documentDirtyRect.intersect(frameGeometry());
+ 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);
- context->save();
-
- context->translate(x(), y());
- documentDirtyRect.move(-x(), -y());
-
- context->translate(-contentsX(), -contentsY());
- documentDirtyRect.move(contentsX(), contentsY());
-
- context->clip(enclosingIntRect(visibleContentRect()));
- static_cast<const FrameView*>(this)->frame()->paint(context, documentDirtyRect);
- context->restore();
-
- // Now paint the scrollbars.
- if (!m_data->scrollbarsSuppressed && (m_data->hBar || m_data->vBar)) {
- context->save();
- IntRect scrollViewDirtyRect = rect;
- scrollViewDirtyRect.intersect(frameGeometry());
- context->translate(x(), y());
- scrollViewDirtyRect.move(-x(), -y());
- if (m_data->hBar)
- m_data->hBar->paint(context, scrollViewDirtyRect);
- if (m_data->vBar)
- m_data->vBar->paint(context, scrollViewDirtyRect);
-
- /*
- * FIXME: TODO: Check if that works with RTL
- */
- // Fill the scroll corner with white.
- IntRect hCorner;
- if (m_data->hBar && width() - m_data->hBar->width() > 0) {
- hCorner = IntRect(m_data->hBar->width(),
- height() - m_data->hBar->height(),
- width() - m_data->hBar->width(),
- m_data->hBar->height());
- if (hCorner.intersects(scrollViewDirtyRect))
- context->fillRect(hCorner, Color::white);
+ if (m_scrollOffset.height() != scroll.height()) {
+ m_verticalAdjustment->value = scroll.height();
+ gtk_adjustment_value_changed(m_verticalAdjustment);
}
-
- if (m_data->vBar && height() - m_data->vBar->height() > 0) {
- IntRect vCorner(width() - m_data->vBar->width(),
- m_data->vBar->height(),
- m_data->vBar->width(),
- height() - m_data->vBar->height());
- if (vCorner != hCorner && vCorner.intersects(scrollViewDirtyRect))
- context->fillRect(vCorner, Color::white);
- }
-
- context->restore();
- }
-}
-
-/*
- * update children but nor our scrollbars. They should not scroll when
- * we scroll our content.
- */
-void ScrollView::geometryChanged() const
-{
- HashSet<Widget*>::const_iterator end = m_data->children.end();
- for (HashSet<Widget*>::const_iterator current = m_data->children.begin(); current != end; ++current)
- (*current)->geometryChanged();
-}
-
-bool ScrollView::scroll(ScrollDirection direction, ScrollGranularity granularity)
-{
- if (direction == ScrollUp || direction == ScrollDown) {
- if (m_data->vBar)
- return m_data->vBar->scroll(direction, granularity);
- } else {
- if (m_data->hBar)
- return m_data->hBar->scroll(direction, granularity);
- }
+ return true;
+ }
return false;
}
-void ScrollView::addToDirtyRegion(const IntRect& containingWindowRect)
-{
- ASSERT(isFrameView());
- const FrameView* frameView = static_cast<const FrameView*>(this);
- Page* page = frameView->frame() ? frameView->frame()->page() : 0;
- if (!page)
- return;
- page->chrome()->addToDirtyRegion(containingWindowRect);
-}
-
-void ScrollView::scrollBackingStore(int dx, int dy, const IntRect& scrollViewRect, const IntRect& clipRect)
+bool ScrollView::platformHasHorizontalAdjustment() const
{
- ASSERT(isFrameView());
- const FrameView* frameView = static_cast<const FrameView*>(this);
- Page* page = frameView->frame() ? frameView->frame()->page() : 0;
- if (!page)
- return;
- page->chrome()->scrollBackingStore(dx, dy, scrollViewRect, clipRect);
-}
-
-void ScrollView::updateBackingStore()
-{
- ASSERT(isFrameView());
- const FrameView* frameView = static_cast<const FrameView*>(this);
- Page* page = frameView->frame() ? frameView->frame()->page() : 0;
- if (!page)
- return;
- page->chrome()->updateBackingStore();
+ return m_horizontalAdjustment != 0;
}
-HashSet<Widget*>* ScrollView::children() const
+bool ScrollView::platformHasVerticalAdjustment() const
{
- return &m_data->children;
+ return m_verticalAdjustment != 0;
}
}
diff --git a/WebCore/platform/gtk/PlatformScrollBarGtk.cpp b/WebCore/platform/gtk/ScrollbarGtk.cpp
index c675ba0..099895d 100644
--- a/WebCore/platform/gtk/PlatformScrollBarGtk.cpp
+++ b/WebCore/platform/gtk/ScrollbarGtk.cpp
@@ -17,19 +17,25 @@
*/
#include "config.h"
-#include "PlatformScrollBar.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;
-static gboolean gtkScrollEventCallback(GtkWidget* widget, GdkEventScroll* event, PlatformScrollbar*)
+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
@@ -37,7 +43,7 @@ static gboolean gtkScrollEventCallback(GtkWidget* widget, GdkEventScroll* event,
return gtk_widget_event(gtk_widget_get_parent(widget), reinterpret_cast<GdkEvent*>(event));
}
-PlatformScrollbar::PlatformScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation,
+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)))
@@ -47,50 +53,45 @@ PlatformScrollbar::PlatformScrollbar(ScrollbarClient* client, ScrollbarOrientati
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(PlatformScrollbar::gtkValueChanged), this);
+ 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);
- setGtkWidget(GTK_WIDGET(scrollBar));
+ setPlatformWidget(GTK_WIDGET(scrollBar));
/*
- * assign a sane default width and height to the ScrollBar, otherwise
+ * assign a sane default width and height to the Scrollbar, otherwise
* we will end up with a 0 width scrollbar.
*/
- resize(PlatformScrollbar::horizontalScrollbarHeight(),
- PlatformScrollbar::verticalScrollbarWidth());
+ resize(ScrollbarTheme::nativeTheme()->scrollbarThickness(),
+ ScrollbarTheme::nativeTheme()->scrollbarThickness());
}
-PlatformScrollbar::~PlatformScrollbar()
+ScrollbarGtk::~ScrollbarGtk()
{
/*
* the Widget does not take over ownership.
*/
- g_signal_handlers_disconnect_by_func(G_OBJECT(gtkWidget()), (gpointer)PlatformScrollbar::gtkValueChanged, this);
- g_signal_handlers_disconnect_by_func(G_OBJECT(gtkWidget()), (gpointer)gtkScrollEventCallback, this);
- g_object_unref(G_OBJECT(gtkWidget()));
+ 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()));
}
-int PlatformScrollbar::width() const
+void ScrollbarGtk::frameRectsChanged() const
{
- return Widget::width();
-}
+ if (!parent() || !parent()->isScrollViewScrollbar(this))
+ return;
-int PlatformScrollbar::height() const
-{
- return Widget::height();
-}
+ IntPoint loc = parent()->convertToContainingWindow(frameRect().location());
-void PlatformScrollbar::setEnabled(bool enabled)
-{
- Widget::setEnabled(enabled);
-}
+ // Don't allow the allocation size to be negative
+ IntSize sz = frameRect().size();
+ sz.clampNegativeToZero();
-void PlatformScrollbar::paint(GraphicsContext* graphicsContext, const IntRect& damageRect)
-{
- Widget::paint(graphicsContext, damageRect);
+ GtkAllocation allocation = { loc.x(), loc.y(), sz.width(), sz.height() };
+ gtk_widget_size_allocate(platformWidget(), &allocation);
}
-void PlatformScrollbar::updateThumbPosition()
+void ScrollbarGtk::updateThumbPosition()
{
if (m_adjustment->value != m_currentPos) {
m_adjustment->value = m_currentPos;
@@ -98,7 +99,7 @@ void PlatformScrollbar::updateThumbPosition()
}
}
-void PlatformScrollbar::updateThumbProportion()
+void ScrollbarGtk::updateThumbProportion()
{
m_adjustment->step_increment = m_lineStep;
m_adjustment->page_increment = m_pageStep;
@@ -107,13 +108,13 @@ void PlatformScrollbar::updateThumbProportion()
gtk_adjustment_changed(m_adjustment);
}
-void PlatformScrollbar::setRect(const IntRect& rect)
+void ScrollbarGtk::setFrameRect(const IntRect& rect)
{
- setFrameGeometry(rect);
- geometryChanged();
+ Widget::setFrameRect(rect);
+ frameRectsChanged();
}
-void PlatformScrollbar::geometryChanged()
+void ScrollbarGtk::frameRectsChanged()
{
if (!parent())
return;
@@ -121,36 +122,29 @@ void PlatformScrollbar::geometryChanged()
ASSERT(parent()->isFrameView());
FrameView* frameView = static_cast<FrameView*>(parent());
- IntRect windowRect = IntRect(frameView->contentsToWindow(frameGeometry().location()), frameGeometry().size());
- GtkAllocation allocation = { windowRect.x(), windowRect.y(), windowRect.width(), windowRect.height() };
- gtk_widget_size_allocate(gtkWidget(), &allocation);
+ 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 PlatformScrollbar::gtkValueChanged(GtkAdjustment*, PlatformScrollbar* that)
+void ScrollbarGtk::gtkValueChanged(GtkAdjustment*, ScrollbarGtk* that)
{
that->setValue(static_cast<int>(gtk_adjustment_get_value(that->m_adjustment)));
}
-static int scrollbarSize()
+void ScrollbarGtk::setEnabled(bool shouldEnable)
{
- static int size = 0;
-
- if (size)
- return size;
-
- MozGtkScrollbarMetrics metrics;
- moz_gtk_get_scrollbar_metrics(&metrics);
- size = metrics.slider_width;
-
- return size;
+ if (enabled() == shouldEnable)
+ return;
+
+ Scrollbar::setEnabled(shouldEnable);
+ if (platformWidget())
+ gtk_widget_set_sensitive(platformWidget(), shouldEnable);
}
-int PlatformScrollbar::horizontalScrollbarHeight()
-{
- return scrollbarSize();
-}
-int PlatformScrollbar::verticalScrollbarWidth()
-{
- return scrollbarSize();
-}
+
diff --git a/WebCore/platform/gtk/PlatformScrollBar.h b/WebCore/platform/gtk/ScrollbarGtk.h
index 88bbfa4..50e9184 100644
--- a/WebCore/platform/gtk/PlatformScrollBar.h
+++ b/WebCore/platform/gtk/ScrollbarGtk.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved.
+ * 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
@@ -23,42 +23,45 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef PlatformScrollBar_h
-#define PlatformScrollBar_h
+#ifndef ScrollbarGtk_h
+#define ScrollbarGtk_h
-#include "Widget.h"
-#include "ScrollBar.h"
+#include "Scrollbar.h"
+#include <wtf/PassRefPtr.h>
typedef struct _GtkAdjustment GtkAdjustment;
namespace WebCore {
-class PlatformScrollbar : public Widget, public Scrollbar {
+class ScrollbarGtk : public Scrollbar {
public:
- PlatformScrollbar(ScrollbarClient*, ScrollbarOrientation, ScrollbarControlSize);
- virtual ~PlatformScrollbar();
+ friend class Scrollbar;
- virtual bool isWidget() const { return true; }
+ 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 int width() const;
- virtual int height() const;
- virtual void setRect(const IntRect&);
virtual void setEnabled(bool);
- virtual void paint(GraphicsContext*, const IntRect& damageRect);
- static int horizontalScrollbarHeight();
- static int verticalScrollbarWidth();
+ virtual void frameRectsChanged() const;
protected:
+ ScrollbarGtk(ScrollbarClient*, ScrollbarOrientation, ScrollbarControlSize);
+
virtual void updateThumbPosition();
virtual void updateThumbProportion();
- virtual void geometryChanged();
-
+ virtual void frameRectsChanged();
+
private:
- static void gtkValueChanged(GtkAdjustment*, PlatformScrollbar*);
+ static void gtkValueChanged(GtkAdjustment*, ScrollbarGtk*);
GtkAdjustment* m_adjustment;
};
}
-#endif // PlatformScrollBar_h
+#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
index e7469c8..fbaa527 100644
--- a/WebCore/platform/gtk/SearchPopupMenuGtk.cpp
+++ b/WebCore/platform/gtk/SearchPopupMenuGtk.cpp
@@ -40,7 +40,7 @@ void SearchPopupMenu::loadRecentSearches(const AtomicString&, Vector<String>&)
bool SearchPopupMenu::enabled()
{
notImplemented();
- return true;
+ 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
index a537ffb..e0a5b60 100644
--- a/WebCore/platform/gtk/SharedTimerGtk.cpp
+++ b/WebCore/platform/gtk/SharedTimerGtk.cpp
@@ -64,7 +64,7 @@ void setSharedTimerFireTime(double fireTime)
stopSharedTimer();
if (intervalInMS == 0)
- sharedTimer = g_idle_add_full(G_PRIORITY_DEFAULT, timeout_cb, NULL, NULL);
+ sharedTimer = g_idle_add(timeout_cb, NULL);
else
sharedTimer = g_timeout_add_full(G_PRIORITY_DEFAULT, intervalInMS, timeout_cb, NULL, NULL);
}
diff --git a/WebCore/platform/gtk/TemporaryLinkStubs.cpp b/WebCore/platform/gtk/TemporaryLinkStubs.cpp
index 525a6f8..5093794 100644
--- a/WebCore/platform/gtk/TemporaryLinkStubs.cpp
+++ b/WebCore/platform/gtk/TemporaryLinkStubs.cpp
@@ -28,14 +28,13 @@
#include "config.h"
#include "AXObjectCache.h"
+#include "DNS.h"
#include "Editor.h"
#include "FrameView.h"
#include "FTPDirectoryDocument.h"
-#include "GlobalHistory.h"
-#include "KURL.h"
#include "NotImplemented.h"
-#include "PluginInfoStore.h"
-#include "SharedBuffer.h"
+#include "PluginView.h"
+#include <float.h>
using namespace WebCore;
@@ -57,25 +56,13 @@ Vector<char> loadResourceIntoArray(const char* resourceName)
/* Completely empty stubs (mostly to allow DRT to run): */
/********************************************************/
-bool WebCore::historyContains(const UChar*, unsigned) { return false; }
+void PluginView::invalidateRegion(NPRegion) { notImplemented(); }
-PluginInfo* PluginInfoStore::createPluginInfoForPluginAtIndex(unsigned) { notImplemented(); return 0;}
-unsigned PluginInfoStore::pluginCount() const { notImplemented(); return 0; }
-String PluginInfoStore::pluginNameForMIMEType(const String& mimeType) { notImplemented(); return String(); }
-bool WebCore::PluginInfoStore::supportsMIMEType(const WebCore::String&) { notImplemented(); return false; }
-void WebCore::refreshPlugins(bool) { notImplemented(); }
-
-
-Color WebCore::focusRingColor() { return 0xFF0000FF; }
-void WebCore::setFocusRingColorChangeFunction(void (*)()) { }
+Color WebCore::focusRingColor() { return Color(); }
namespace WebCore {
-Vector<String> supportedKeySizes() { notImplemented(); return Vector<String>(); }
+void getSupportedKeySizes(Vector<String>&) { notImplemented(); }
String signedPublicKeyAndChallengeString(unsigned keySizeIndex, const String &challengeString, const KURL &url) { return String(); }
-float userIdleTime() { notImplemented(); return 0.0; }
+float userIdleTime() { notImplemented(); return FLT_MAX; } // return an arbitrarily high userIdleTime so that releasing pages from the page cache isn't postponed
-String KURL::fileSystemPath() const { notImplemented(); return String(); }
-
-PassRefPtr<SharedBuffer> SharedBuffer::createWithContentsOfFile(const String&) { notImplemented(); return 0; }
}
-
diff --git a/WebCore/platform/gtk/ThreadingGtk.cpp b/WebCore/platform/gtk/ThreadingGtk.cpp
deleted file mode 100644
index 5ce6ba2..0000000
--- a/WebCore/platform/gtk/ThreadingGtk.cpp
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
- *
- * 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.
- * 3. Neither the name of Apple Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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 "Threading.h"
-
-#include "HashMap.h"
-#include "Logging.h"
-
-#include <glib.h>
-
-namespace WebCore {
-
-struct FunctionWithContext {
- MainThreadFunction* function;
- void* context;
-};
-
-static gboolean callFunctionOnMainThread(gpointer data)
-{
- FunctionWithContext* functionWithContext = static_cast<FunctionWithContext*>(data);
- functionWithContext->function(functionWithContext->context);
- delete functionWithContext;
- return FALSE;
-}
-
-void callOnMainThread(MainThreadFunction* function, void* context)
-{
- ASSERT(function);
- FunctionWithContext* functionWithContext = new FunctionWithContext;
- functionWithContext->function = function;
- functionWithContext->context = context;
- g_timeout_add(0, callFunctionOnMainThread, functionWithContext);
-}
-
-void initializeThreading()
-{
- if (!g_thread_supported())
- g_thread_init(NULL);
- ASSERT(g_thread_supported());
-}
-
-static Mutex& threadMapMutex()
-{
- static Mutex mutex;
- return mutex;
-}
-
-static HashMap<ThreadIdentifier, GThread*>& threadMap()
-{
- static HashMap<ThreadIdentifier, GThread*> map;
- return map;
-}
-
-static ThreadIdentifier establishIdentifierForThread(GThread*& thread)
-{
- MutexLocker locker(threadMapMutex());
-
- static ThreadIdentifier identifierCount = 1;
-
- threadMap().add(identifierCount, thread);
-
- return identifierCount++;
-}
-
-static ThreadIdentifier identifierByGthreadHandle(GThread*& thread)
-{
- MutexLocker locker(threadMapMutex());
-
- HashMap<ThreadIdentifier, GThread*>::iterator i = threadMap().begin();
- for (; i != threadMap().end(); ++i) {
- if (i->second == thread)
- return i->first;
- }
-
- return 0;
-}
-
-static GThread* threadForIdentifier(ThreadIdentifier id)
-{
- MutexLocker locker(threadMapMutex());
-
- return threadMap().get(id);
-}
-
-static void clearThreadForIdentifier(ThreadIdentifier id)
-{
- MutexLocker locker(threadMapMutex());
-
- ASSERT(threadMap().contains(id));
-
- threadMap().remove(id);
-}
-
-ThreadIdentifier createThread(ThreadFunction entryPoint, void* data)
-{
- GThread* thread;
- if (!(thread = g_thread_create(entryPoint, data, TRUE, 0))) {
- LOG_ERROR("Failed to create thread at entry point %p with data %p", entryPoint, data);
- return 0;
- }
-
- ThreadIdentifier threadID = establishIdentifierForThread(thread);
- LOG(Threading, "Created thread with thread id %u", threadID);
- return threadID;
-}
-
-int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
-{
- ASSERT(threadID);
-
- GThread* thread = threadForIdentifier(threadID);
-
- *result = g_thread_join(thread);
-
- clearThreadForIdentifier(threadID);
- return 0;
-}
-
-void detachThread(ThreadIdentifier)
-{
-}
-
-ThreadIdentifier currentThread()
-{
- GThread* currentThread = g_thread_self();
- if (ThreadIdentifier id = identifierByGthreadHandle(currentThread))
- return id;
- return establishIdentifierForThread(currentThread);
-}
-
-Mutex::Mutex()
- : m_mutex(g_mutex_new())
-{
-}
-
-Mutex::~Mutex()
-{
- g_mutex_free(m_mutex);
-}
-
-void Mutex::lock()
-{
- g_mutex_lock(m_mutex);
-}
-
-bool Mutex::tryLock()
-{
- return g_mutex_trylock(m_mutex);
-}
-
-void Mutex::unlock()
-{
- g_mutex_unlock(m_mutex);
-}
-
-ThreadCondition::ThreadCondition()
- : m_condition(g_cond_new())
-{
-}
-
-ThreadCondition::~ThreadCondition()
-{
- g_cond_free(m_condition);
-}
-
-void ThreadCondition::wait(Mutex& mutex)
-{
- g_cond_wait(m_condition, mutex.impl());
-}
-
-void ThreadCondition::signal()
-{
- g_cond_signal(m_condition);
-}
-
-void ThreadCondition::broadcast()
-{
- g_cond_broadcast(m_condition);
-}
-
-
-}
diff --git a/WebCore/platform/gtk/WheelEventGtk.cpp b/WebCore/platform/gtk/WheelEventGtk.cpp
index 3368f25..fbe31f7 100644
--- a/WebCore/platform/gtk/WheelEventGtk.cpp
+++ b/WebCore/platform/gtk/WheelEventGtk.cpp
@@ -29,9 +29,11 @@
#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;
@@ -57,12 +59,21 @@ PlatformWheelEvent::PlatformWheelEvent(GdkEventScroll* event)
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;
- m_metaKey = event->state & GDK_MOD2_MASK;
- m_isContinuous = false;
+#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
index 1d5f021..82fed74 100644
--- a/WebCore/platform/gtk/WidgetGtk.cpp
+++ b/WebCore/platform/gtk/WidgetGtk.cpp
@@ -31,6 +31,7 @@
#include "Cursor.h"
#include "FrameView.h"
#include "GraphicsContext.h"
+#include "HostWindow.h"
#include "IntRect.h"
#include "NotImplemented.h"
#include "RenderObject.h"
@@ -42,97 +43,38 @@ namespace WebCore {
class WidgetPrivate {
public:
- GtkWidget* widget;
- WidgetClient* client;
- IntRect frameRect;
-
- ScrollView* parent;
- GtkContainer* containingWindow;
- bool suppressInvalidation;
GdkCursor* cursor;
-
- GdkDrawable* gdkDrawable() const
- {
- return widget ? widget->window : 0;
- }
};
-Widget::Widget()
- : data(new WidgetPrivate)
-{
- data->widget = 0;
- data->parent = 0;
- data->containingWindow = 0;
- data->suppressInvalidation = false;
- data->cursor = 0;
-}
-
-GtkWidget* Widget::gtkWidget() const
-{
- return data->widget;
-}
-
-void Widget::setGtkWidget(GtkWidget* widget)
+Widget::Widget(PlatformWidget widget)
+ : m_data(new WidgetPrivate)
{
- data->widget = widget;
+ init(widget);
+ m_data->cursor = 0;
}
Widget::~Widget()
{
ASSERT(!parent());
- delete data;
-}
-
-void Widget::setContainingWindow(GtkContainer* containingWindow)
-{
- data->containingWindow = containingWindow;
-}
-
-GtkContainer* Widget::containingWindow() const
-{
- return data->containingWindow;
-}
-
-void Widget::setClient(WidgetClient* c)
-{
- data->client = c;
-}
-
-WidgetClient* Widget::client() const
-{
- return data->client;
-}
-
-IntRect Widget::frameGeometry() const
-{
- return data->frameRect;
-}
-
-void Widget::setFrameGeometry(const IntRect& r)
-{
- data->frameRect = r;
-}
-
-void Widget::setParent(ScrollView* v)
-{
- data->parent = v;
-}
-
-ScrollView* Widget::parent() const
-{
- return data->parent;
+ releasePlatformWidget();
+ delete m_data;
}
void Widget::setFocus()
{
- gtk_widget_grab_focus(gtkWidget() ? gtkWidget() : GTK_WIDGET(containingWindow()));
+ gtk_widget_grab_focus(platformWidget() ? platformWidget() : GTK_WIDGET(root()->hostWindow()->platformWindow()));
}
Cursor Widget::cursor()
{
- return Cursor(data->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();
@@ -143,62 +85,42 @@ void Widget::setCursor(const Cursor& cursor)
// gdk_window_set_cursor() in certain GDK backends seems to be an
// expensive operation, so avoid it if possible.
- if (pcur == data->cursor)
+ if (pcur == m_data->cursor)
return;
- gdk_window_set_cursor(data->gdkDrawable() ? GDK_WINDOW(data->gdkDrawable()) : GTK_WIDGET(containingWindow())->window, pcur);
- data->cursor = pcur;
+ 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 (!gtkWidget())
+ if (!platformWidget())
return;
- gtk_widget_show(gtkWidget());
+ gtk_widget_show(platformWidget());
}
void Widget::hide()
{
- if (!gtkWidget())
+ if (!platformWidget())
return;
- gtk_widget_hide(gtkWidget());
-}
-
-void Widget::setEnabled(bool shouldEnable)
-{
- if (!gtkWidget())
- return;
- gtk_widget_set_sensitive(gtkWidget(), shouldEnable);
-}
-
-bool Widget::isEnabled() const
-{
- if (!gtkWidget())
- return false;
- return GTK_WIDGET_IS_SENSITIVE(gtkWidget());
-}
-
-void Widget::removeFromParent()
-{
- if (parent())
- parent()->removeChild(this);
+ 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 geometryChanged positioned
+ * 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 (!gtkWidget())
+ if (!platformWidget())
return;
if (!context->gdkExposeEvent())
return;
- GtkWidget* widget = gtkWidget();
+ GtkWidget* widget = platformWidget();
ASSERT(GTK_WIDGET_NO_WINDOW(widget));
GdkEvent* event = gdk_event_new(GDK_EXPOSE);
@@ -226,85 +148,33 @@ void Widget::setIsSelected(bool)
notImplemented();
}
-void Widget::invalidate()
+IntRect Widget::frameRect() const
{
- invalidateRect(IntRect(0, 0, width(), height()));
+ return m_frame;
}
-void Widget::invalidateRect(const IntRect& rect)
+void Widget::setFrameRect(const IntRect& rect)
{
- if (data->suppressInvalidation)
- return;
-
- if (!parent()) {
- gtk_widget_queue_draw_area(GTK_WIDGET(containingWindow()), rect.x(), rect.y(),
- rect.width(), rect.height());
- if (isFrameView())
- static_cast<FrameView*>(this)->addToDirtyRegion(rect);
- return;
- }
-
- // Get the root widget.
- ScrollView* outermostView = parent();
- while (outermostView && outermostView->parent())
- outermostView = outermostView->parent();
- if (!outermostView)
- return;
-
- IntRect windowRect = convertToContainingWindow(rect);
- gtk_widget_queue_draw_area(GTK_WIDGET(containingWindow()), windowRect.x(), windowRect.y(),
- windowRect.width(), windowRect.height());
- outermostView->addToDirtyRegion(windowRect);
+ m_frame = rect;
}
-IntPoint Widget::convertToContainingWindow(const IntPoint& point) const
+void Widget::releasePlatformWidget()
{
- IntPoint windowPoint = point;
- for (const Widget *parentWidget = parent(), *childWidget = this;
- parentWidget;
- childWidget = parentWidget, parentWidget = parentWidget->parent())
- windowPoint = parentWidget->convertChildToSelf(childWidget, windowPoint);
- return windowPoint;
-}
-
-IntPoint Widget::convertFromContainingWindow(const IntPoint& point) const
-{
- IntPoint widgetPoint = point;
- for (const Widget *parentWidget = parent(), *childWidget = this;
- parentWidget;
- childWidget = parentWidget, parentWidget = parentWidget->parent())
- widgetPoint = parentWidget->convertSelfToChild(childWidget, widgetPoint);
- return widgetPoint;
-}
-
-IntRect Widget::convertToContainingWindow(const IntRect& rect) const
-{
- IntRect convertedRect = rect;
- convertedRect.setLocation(convertToContainingWindow(convertedRect.location()));
- return convertedRect;
-}
-
-IntPoint Widget::convertChildToSelf(const Widget* child, const IntPoint& point) const
-{
- return IntPoint(point.x() + child->x(), point.y() + child->y());
-}
-
-IntPoint Widget::convertSelfToChild(const Widget* child, const IntPoint& point) const
-{
- return IntPoint(point.x() - child->x(), point.y() - child->y());
-}
-
-bool Widget::suppressInvalidation() const
-{
- return data->suppressInvalidation;
+ if (!platformWidget())
+ return;
+ g_object_unref(platformWidget());
}
-void Widget::setSuppressInvalidation(bool suppress)
+void Widget::retainPlatformWidget()
{
- data->suppressInvalidation = suppress;
+ 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
}
-void Widget::geometryChanged() const
-{
-}
}
diff --git a/WebCore/platform/gtk/gtk2drawing.c b/WebCore/platform/gtk/gtk2drawing.c
index 475e9fd..83b4cb4 100644
--- a/WebCore/platform/gtk/gtk2drawing.c
+++ b/WebCore/platform/gtk/gtk2drawing.c
@@ -23,6 +23,7 @@
* 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
@@ -57,6 +58,7 @@
static GtkWidget* gProtoWindow;
static GtkWidget* gButtonWidget;
static GtkWidget* gToggleButtonWidget;
+static GtkWidget* gButtonArrowWidget;
static GtkWidget* gCheckboxWidget;
static GtkWidget* gRadiobuttonWidget;
static GtkWidget* gHorizScrollbarWidget;
@@ -65,11 +67,14 @@ static GtkWidget* gSpinWidget;
static GtkWidget* gHScaleWidget;
static GtkWidget* gVScaleWidget;
static GtkWidget* gEntryWidget;
-static GtkWidget* gArrowWidget;
-static GtkWidget* gOptionMenuWidget;
+static GtkWidget* gComboBoxWidget;
+static GtkWidget* gComboBoxButtonWidget;
+static GtkWidget* gComboBoxArrowWidget;
+static GtkWidget* gComboBoxSeparatorWidget;
static GtkWidget* gComboBoxEntryWidget;
-static GtkWidget* gDropdownEntryWidget;
-static GtkWidget* gDropdownButtonWidget;
+static GtkWidget* gComboBoxEntryTextareaWidget;
+static GtkWidget* gComboBoxEntryButtonWidget;
+static GtkWidget* gComboBoxEntryArrowWidget;
static GtkWidget* gHandleBoxWidget;
static GtkWidget* gToolbarWidget;
static GtkWidget* gFrameWidget;
@@ -81,8 +86,10 @@ 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;
@@ -90,14 +97,22 @@ static GtkWidget* gToolbarSeparatorWidget;
static GtkWidget* gMenuSeparatorWidget;
static GtkWidget* gHPanedWidget;
static GtkWidget* gVPanedWidget;
-
-static GtkShadowType gMenuBarShadowType;
-static GtkShadowType gToolbarShadowType;
+static GtkWidget* gScrolledWindowWidget;
static style_prop_t style_prop_func;
-static gboolean have_menu_shadow_type;
+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)
{
@@ -111,6 +126,7 @@ 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;
}
@@ -127,6 +143,7 @@ setup_widget_prototype(GtkWidget* widget)
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;
}
@@ -173,6 +190,19 @@ ensure_toggle_button_widget()
}
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) {
@@ -240,64 +270,219 @@ ensure_entry_widget()
return MOZ_GTK_SUCCESS;
}
-static gint
-ensure_option_menu_widget()
-{
- if (!gOptionMenuWidget) {
- gOptionMenuWidget = gtk_option_menu_new();
- setup_widget_prototype(gOptionMenuWidget);
+/* 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);
}
- return MOZ_GTK_SUCCESS;
}
-static gint
-ensure_combo_box_entry_widget()
-{
- if (!gComboBoxEntryWidget) {
- gComboBoxEntryWidget = gtk_combo_box_entry_new();
- setup_widget_prototype(gComboBoxEntryWidget);
- }
- return MOZ_GTK_SUCCESS;
+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_dropdown_entry_widget()
+ensure_combo_box_widgets()
{
- if (!gDropdownEntryWidget) {
- ensure_combo_box_entry_widget();
+ 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;
+ }
- gDropdownEntryWidget = GTK_BIN(gComboBoxEntryWidget)->child;
- gtk_widget_realize(gDropdownEntryWidget);
+ 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_dropdown_button(GtkWidget *widget,
- gpointer client_data)
-{
- if (GTK_IS_TOGGLE_BUTTON(widget))
- gDropdownButtonWidget = widget;
+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_arrow_widget()
+ensure_combo_box_entry_widgets()
{
- if (!gArrowWidget) {
- ensure_combo_box_entry_widget();
+ GtkWidget* buttonChild;
- gtk_container_forall(GTK_CONTAINER(gComboBoxEntryWidget),
- moz_gtk_get_dropdown_button,
- NULL);
+ 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);
+ }
- gArrowWidget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
- gtk_container_add(GTK_CONTAINER(GTK_BIN(gDropdownButtonWidget)->child),
- gArrowWidget);
- gtk_widget_realize(gArrowWidget);
+ /* 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()
{
@@ -316,8 +501,7 @@ ensure_toolbar_widget()
gToolbarWidget = gtk_toolbar_new();
gtk_container_add(GTK_CONTAINER(gHandleBoxWidget), gToolbarWidget);
gtk_widget_realize(gToolbarWidget);
- gtk_widget_style_get(gToolbarWidget, "shadow_type", &gToolbarShadowType,
- NULL);
+ g_object_set_data(G_OBJECT(gToolbarWidget), "transparent-bg-hint", TRUE);
}
return MOZ_GTK_SUCCESS;
}
@@ -339,6 +523,7 @@ 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;
}
@@ -391,8 +576,6 @@ ensure_menu_bar_widget()
if (!gMenuBarWidget) {
gMenuBarWidget = gtk_menu_bar_new();
setup_widget_prototype(gMenuBarWidget);
- gtk_widget_style_get(gMenuBarWidget, "shadow_type", &gMenuBarShadowType,
- NULL);
}
return MOZ_GTK_SUCCESS;
}
@@ -406,6 +589,8 @@ ensure_menu_bar_item_widget()
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;
}
@@ -419,6 +604,8 @@ ensure_menu_popup_widget()
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;
}
@@ -432,6 +619,23 @@ ensure_menu_item_widget()
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;
}
@@ -445,6 +649,8 @@ ensure_menu_separator_widget()
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;
}
@@ -458,6 +664,8 @@ ensure_check_menu_item_widget()
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;
}
@@ -476,16 +684,45 @@ static gint
ensure_tree_header_cell_widget()
{
if(!gTreeHeaderCellWidget) {
- GtkTreeViewColumn* treeViewColumn;
- ensure_tree_view_widget();
+ /*
+ * 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;
- treeViewColumn = gtk_tree_view_column_new();
- gtk_tree_view_column_set_title(treeViewColumn, "M");
+ ensure_tree_view_widget();
- gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), treeViewColumn);
- gTreeHeaderCellWidget = treeViewColumn->button;
- gtk_tree_view_column_set_sort_indicator(treeViewColumn, TRUE);
- gTreeHeaderSortArrowWidget = treeViewColumn->arrow;
+ /* 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;
}
@@ -500,6 +737,16 @@ ensure_expander_widget()
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)
{
@@ -566,6 +813,13 @@ moz_gtk_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
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;
@@ -576,7 +830,7 @@ moz_gtk_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
shadow_type = button_state == GTK_STATE_ACTIVE ||
state->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
- if (state->isDefault && GTK_BUTTON(widget)->relief == GTK_RELIEF_NORMAL) {
+ if (state->isDefault && relief == GTK_RELIEF_NORMAL) {
gtk_paint_box(style, drawable, button_state, shadow_type, cliprect,
widget, "buttondefault", x, y, width, height);
}
@@ -611,16 +865,32 @@ moz_gtk_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
}
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_menu_shadow_type =
- (gtk_major_version > 2 ||
- (gtk_major_version == 2 && gtk_minor_version >= 1));
+ 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;
}
@@ -664,45 +934,6 @@ moz_gtk_widget_get_focus(GtkWidget* widget, gboolean* interior_focus,
return MOZ_GTK_SUCCESS;
}
-static gint
-moz_gtk_option_menu_get_metrics(gboolean* interior_focus,
- GtkRequisition* indicator_size,
- GtkBorder* indicator_spacing,
- gint* focus_width,
- gint* focus_pad)
-{
- static const GtkRequisition default_indicator_size = { 7, 13 };
- static const GtkBorder default_indicator_spacing = { 7, 5, 2, 2 };
- /* these default values are not used in gtkoptionmenu.c
- static const gboolean default_interior_focus = TRUE;
- static const gint default_focus_width = 1;
- static const gint default_focus_pad = 0; */
- GtkRequisition *tmp_indicator_size;
- GtkBorder *tmp_indicator_spacing;
-
- gtk_widget_style_get(gOptionMenuWidget,
- "interior_focus", interior_focus,
- "indicator_size", &tmp_indicator_size,
- "indicator_spacing", &tmp_indicator_spacing,
- "focus_line_width", focus_width,
- "focus_padding", focus_pad,
- NULL);
-
- if (tmp_indicator_size)
- *indicator_size = *tmp_indicator_size;
- else
- *indicator_size = default_indicator_size;
- if (tmp_indicator_spacing)
- *indicator_spacing = *tmp_indicator_spacing;
- else
- *indicator_spacing = default_indicator_spacing;
-
- gtk_requisition_free(tmp_indicator_size);
- gtk_border_free(tmp_indicator_spacing);
-
- return MOZ_GTK_SUCCESS;
-}
-
gint
moz_gtk_splitter_get_metrics(gint orientation, gint* size)
{
@@ -716,6 +947,25 @@ moz_gtk_splitter_get_metrics(gint orientation, gint* size)
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,
@@ -726,6 +976,7 @@ moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect,
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;
@@ -737,11 +988,19 @@ moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect,
w = gCheckboxWidget;
}
- /* offset by indicator_spacing, and centered vertically within the rect */
- x = rect->x + indicator_spacing;
+ /*
+ * 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);
@@ -756,8 +1015,8 @@ moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect,
width, height);
if (state->focused) {
gtk_paint_focus(style, drawable, GTK_STATE_ACTIVE, cliprect,
- gRadiobuttonWidget, "radiobutton", rect->x, rect->y,
- rect->width, rect->height);
+ gRadiobuttonWidget, "radiobutton", focus_x, focus_y,
+ focus_width, focus_height);
}
}
else {
@@ -765,8 +1024,8 @@ moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect,
gCheckboxWidget, "checkbutton", x, y, width, height);
if (state->focused) {
gtk_paint_focus(style, drawable, GTK_STATE_ACTIVE, cliprect,
- gCheckboxWidget, "checkbutton", rect->x, rect->y,
- rect->width, rect->height);
+ gCheckboxWidget, "checkbutton", focus_x, focus_y,
+ focus_width, focus_height);
}
}
@@ -774,20 +1033,63 @@ moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect,
}
static gint
-calculate_arrow_dimensions(GdkRectangle* rect, GdkRectangle* arrow_rect)
+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)
{
- GtkMisc* misc = GTK_MISC(gArrowWidget);
+ /* defined in gtkarrow.c */
+ gfloat arrow_scaling = 0.7;
+ gfloat xalign, xpad;
+ gint extent;
+ GtkMisc* misc = GTK_MISC(arrow);
- gint extent = MIN(rect->width - misc->xpad * 2,
- rect->height - misc->ypad * 2);
+ if (have_arrow_scaling)
+ gtk_widget_style_get(arrow, "arrow_scaling", &arrow_scaling, NULL);
- arrow_rect->x = ((rect->x + misc->xpad) * (1.0 - misc->xalign) +
- (rect->x + rect->width - extent - misc->xpad) *
- misc->xalign);
+ extent = MIN((rect->width - misc->xpad * 2),
+ (rect->height - misc->ypad * 2)) * arrow_scaling;
- arrow_rect->y = ((rect->y + misc->ypad) * (1.0 - misc->yalign) +
- (rect->y + rect->height - extent - misc->ypad) *
- misc->yalign);
+ 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;
@@ -803,11 +1105,11 @@ moz_gtk_scrollbar_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
GtkStateType state_type = ConvertGtkState(state);
GtkShadowType shadow_type = (state->active) ?
GTK_SHADOW_IN : GTK_SHADOW_OUT;
- GdkRectangle button_rect;
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";
@@ -860,20 +1162,26 @@ moz_gtk_scrollbar_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
style = scrollbar->style;
- ensure_arrow_widget();
-
- calculate_arrow_dimensions(rect, &button_rect);
- TSOffsetStyleGCs(style, button_rect.x, button_rect.y);
+ TSOffsetStyleGCs(style, rect->x, rect->y);
gtk_paint_box(style, drawable, state_type, shadow_type, cliprect,
- scrollbar, detail, button_rect.x, button_rect.y,
- button_rect.width, button_rect.height);
+ 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;
- arrow_rect.width = button_rect.width / 2;
- arrow_rect.height = button_rect.height / 2;
- arrow_rect.x = button_rect.x + (button_rect.width - arrow_rect.width) / 2;
- arrow_rect.y = button_rect.y +
- (button_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,
@@ -928,9 +1236,11 @@ moz_gtk_scrollbar_thumb_paint(GtkThemeWidgetType widget,
{
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();
@@ -971,10 +1281,18 @@ moz_gtk_scrollbar_thumb_paint(GtkThemeWidgetType widget,
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, GTK_SHADOW_OUT, cliprect,
+ 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) ?
@@ -1167,52 +1485,87 @@ moz_gtk_vpaned_paint(GdkDrawable* drawable, GdkRectangle* rect,
}
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;
- /* paint the background first */
- x = XTHICKNESS(style);
- y = YTHICKNESS(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);
- TSOffsetStyleGCs(style, rect->x + x, rect->y + y);
- gtk_paint_flat_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_NONE,
- cliprect, widget, "entry_bg", rect->x + x,
- rect->y + y, rect->width - 2*x, rect->height - 2*y);
+ /* 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);
+ }
- gtk_widget_style_get(widget,
- "interior-focus", &interior_focus,
- "focus-line-width", &focus_width,
- NULL);
+ /* Get the position of the inner window, see _gtk_entry_get_borders */
+ x = XTHICKNESS(style);
+ y = YTHICKNESS(style);
- /*
- * Now paint the shadow and focus border.
- *
- * gtk+ is able to draw over top of the entry when it gains focus,
- * so the non-focused text border is implicitly already drawn when
- * the entry is drawn in a focused state.
- *
- * Gecko doesn't quite work this way, so always draw the non-focused
- * shadow, then draw the shadow again, inset, if we're focused.
- */
+ 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. */
+ /* 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) {
@@ -1225,19 +1578,18 @@ moz_gtk_entry_paint(GdkDrawable* drawable, GdkRectangle* rect,
}
}
- TSOffsetStyleGCs(style, x, y);
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) {
- TSOffsetStyleGCs(style, rect->x, rect->y);
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! */
+ /* 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);
}
@@ -1255,7 +1607,10 @@ moz_gtk_treeview_paint(GdkDrawable* drawable, GdkRectangle* rect,
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 */
@@ -1267,20 +1622,21 @@ moz_gtk_treeview_paint(GdkDrawable* drawable, GdkRectangle* rect,
gtk_widget_modify_bg(gTreeViewWidget, state_type,
&gTreeViewWidget->style->base[state_type]);
- style = gTreeViewWidget->style;
+ 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(style, drawable, state_type, GTK_SHADOW_NONE,
- cliprect, gTreeViewWidget, "treeview",
+ 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, gTreeViewWidget, "scrolled_window",
+ cliprect, gScrolledWindowWidget, "scrolled_window",
rect->x, rect->y, rect->width, rect->height);
return MOZ_GTK_SUCCESS;
@@ -1289,8 +1645,11 @@ moz_gtk_treeview_paint(GdkDrawable* drawable, GdkRectangle* rect,
static gint
moz_gtk_tree_header_cell_paint(GdkDrawable* drawable, GdkRectangle* rect,
GdkRectangle* cliprect, GtkWidgetState* state,
- GtkTextDirection direction)
+ 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;
@@ -1375,73 +1734,84 @@ moz_gtk_expander_paint(GdkDrawable* drawable, GdkRectangle* rect,
}
static gint
-moz_gtk_option_menu_paint(GdkDrawable* drawable, GdkRectangle* rect,
- GdkRectangle* cliprect, GtkWidgetState* state,
- GtkTextDirection direction)
+moz_gtk_combo_box_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect, GtkWidgetState* state,
+ gboolean ishtml, GtkTextDirection direction)
{
- GtkStyle* style;
+ GdkRectangle arrow_rect, real_arrow_rect;
+ gint arrow_size, separator_width = 0;
+ gboolean wide_separators = FALSE;
GtkStateType state_type = ConvertGtkState(state);
- gint x = rect->x, y=rect->y, width=rect->width, height=rect->height;
- gint tab_x, tab_y;
- gboolean interior_focus;
- GtkRequisition indicator_size;
- GtkBorder indicator_spacing;
- gint focus_width;
- gint focus_pad;
+ GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
+ GtkStyle* style;
+ GtkRequisition arrow_req;
- ensure_option_menu_widget();
- gtk_widget_set_direction(gOptionMenuWidget, direction);
- moz_gtk_option_menu_get_metrics(&interior_focus, &indicator_size,
- &indicator_spacing, &focus_width,
- &focus_pad);
+ ensure_combo_box_widgets();
- style = gOptionMenuWidget->style;
+ /* 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);
- 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);
- }
+ 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;
- TSOffsetStyleGCs(style, x, y);
- gtk_paint_box(style, drawable, state_type, GTK_SHADOW_OUT,
- cliprect, gOptionMenuWidget, "optionmenu",
- x, y, width, height);
-
- if (direction == GTK_TEXT_DIR_RTL) {
- tab_x = x + indicator_spacing.right + XTHICKNESS(style);
+ 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 {
- tab_x = x + width - indicator_size.width - indicator_spacing.right -
- XTHICKNESS(style);
+ 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);
}
- tab_y = y + (height - indicator_size.height) / 2;
- TSOffsetStyleGCs(style, tab_x, tab_y);
- gtk_paint_tab(style, drawable, state_type, GTK_SHADOW_OUT, cliprect,
- gOptionMenuWidget, "optionmenutab", tab_x, tab_y,
- indicator_size.width, indicator_size.height);
-
- if (state->focused) {
- if (interior_focus) {
- x += XTHICKNESS(style) + focus_pad;
- y += YTHICKNESS(style) + focus_pad;
- /* Standard GTK combos have their focus ring around the entire
- control, not just the text bit */
- width -= 2 * (XTHICKNESS(style) + focus_pad);
- height -= 2 * (YTHICKNESS(style) + 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, state_type, cliprect, gOptionMenuWidget,
- "button", x, y, width, height);
- }
-
return MOZ_GTK_SUCCESS;
}
@@ -1454,63 +1824,66 @@ moz_gtk_downarrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
GdkRectangle arrow_rect;
- ensure_arrow_widget();
- style = gArrowWidget->style;
+ ensure_button_arrow_widget();
+ style = gButtonArrowWidget->style;
- arrow_rect.x = rect->x + 1 + XTHICKNESS(style);
- arrow_rect.y = rect->y + 1 + YTHICKNESS(style);
- arrow_rect.width = MAX(1, rect->width - (arrow_rect.x - rect->x) * 2);
- arrow_rect.height = MAX(1, rect->height - (arrow_rect.y - rect->y) * 2);
+ 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,
- gArrowWidget, "arrow", GTK_ARROW_DOWN, TRUE,
+ 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_dropdown_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
- GdkRectangle* cliprect, GtkWidgetState* state,
- GtkTextDirection direction)
+moz_gtk_combo_box_entry_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
+ GdkRectangle* cliprect,
+ GtkWidgetState* state,
+ gboolean input_focus,
+ GtkTextDirection direction)
{
- static gfloat arrow_scaling = 0.7;
- gint real_arrow_padding;
+ 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_arrow_widget();
- gtk_widget_set_direction(gDropdownButtonWidget, direction);
+ 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,
- gDropdownButtonWidget, direction);
+ gComboBoxEntryButtonWidget, direction);
- /* This mirrors gtkbutton's child positioning */
- style = gDropdownButtonWidget->style;
- arrow_rect.x = rect->x + 1 + XTHICKNESS(style);
- arrow_rect.y = rect->y + 1 + YTHICKNESS(style);
- arrow_rect.width = MAX(1, rect->width - (arrow_rect.x - rect->x) * 2);
- arrow_rect.height = MAX(1, rect->height - (arrow_rect.y - rect->y) * 2);
-
- calculate_arrow_dimensions(&arrow_rect, &real_arrow_rect);
- style = gArrowWidget->style;
- TSOffsetStyleGCs(style, real_arrow_rect.x, real_arrow_rect.y);
+ 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;
+ }
- real_arrow_rect.width = real_arrow_rect.height =
- MIN (real_arrow_rect.width, real_arrow_rect.height) * arrow_scaling;
+ calculate_arrow_rect(gComboBoxEntryArrowWidget,
+ &arrow_rect, &real_arrow_rect, direction);
- real_arrow_padding = floor((arrow_rect.width - real_arrow_rect.width) / 2 + 0.5);
- real_arrow_rect.x = arrow_rect.x + real_arrow_padding;
- if (direction == GTK_TEXT_DIR_RTL)
- real_arrow_rect.x = arrow_rect.x + arrow_rect.width -
- real_arrow_rect.width - real_arrow_padding;
- real_arrow_rect.y = floor (arrow_rect.y + ((arrow_rect.height - real_arrow_rect.height) / 2) + 0.5);
+ style = gComboBoxEntryArrowWidget->style;
+ TSOffsetStyleGCs(style, real_arrow_rect.x, real_arrow_rect.y);
gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
- gDropdownButtonWidget, "arrow", GTK_ARROW_DOWN, TRUE,
+ gComboBoxEntryArrowWidget, "arrow", GTK_ARROW_DOWN, TRUE,
real_arrow_rect.x, real_arrow_rect.y,
real_arrow_rect.width, real_arrow_rect.height);
@@ -1624,7 +1997,9 @@ moz_gtk_toolbar_paint(GdkDrawable* drawable, GdkRectangle* rect,
cliprect, rect->x, rect->y,
rect->width, rect->height);
- gtk_paint_box (style, drawable, GTK_STATE_NORMAL, gToolbarShadowType,
+ 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);
@@ -1637,9 +2012,9 @@ moz_gtk_toolbar_separator_paint(GdkDrawable* drawable, GdkRectangle* rect,
GtkTextDirection direction)
{
GtkStyle* style;
- gint separator_width;
+ gint separator_width = 0;
gint paint_width;
- gboolean wide_separators;
+ gboolean wide_separators = FALSE;
/* Defined as constants in GTK+ 2.10.14 */
const double start_fraction = 0.2;
@@ -1650,10 +2025,11 @@ moz_gtk_toolbar_separator_paint(GdkDrawable* drawable, GdkRectangle* rect,
style = gToolbarSeparatorWidget->style;
- gtk_widget_style_get(gToolbarWidget,
- "wide-separators", &wide_separators,
- "separator-width", &separator_width,
- NULL);
+ if (have_2_10)
+ gtk_widget_style_get(gToolbarWidget,
+ "wide-separators", &wide_separators,
+ "separator-width", &separator_width,
+ NULL);
TSOffsetStyleGCs(style, rect->x, rect->y);
@@ -1965,6 +2341,36 @@ moz_gtk_tabpanels_paint(GdkDrawable* drawable, GdkRectangle* rect,
}
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)
{
@@ -1973,13 +2379,16 @@ moz_gtk_menu_bar_paint(GdkDrawable* drawable, GdkRectangle* rect,
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, gMenuBarShadowType,
+
+ 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;
@@ -2011,9 +2420,9 @@ moz_gtk_menu_separator_paint(GdkDrawable* drawable, GdkRectangle* rect,
GdkRectangle* cliprect, GtkTextDirection direction)
{
GtkStyle* style;
- gboolean wide_separators;
- gint separator_height;
- guint horizontal_padding;
+ gboolean wide_separators = FALSE;
+ gint separator_height = 0;
+ guint horizontal_padding = 0;
gint paint_height;
ensure_menu_separator_widget();
@@ -2021,9 +2430,13 @@ moz_gtk_menu_separator_paint(GdkDrawable* drawable, GdkRectangle* rect,
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,
- "wide-separators", &wide_separators,
- "separator-height", &separator_height,
"horizontal-padding", &horizontal_padding,
NULL);
@@ -2077,12 +2490,9 @@ moz_gtk_menu_item_paint(GdkDrawable* drawable, GdkRectangle* rect,
style = item_widget->style;
TSOffsetStyleGCs(style, rect->x, rect->y);
- if (have_menu_shadow_type) {
- gtk_widget_style_get(item_widget, "selected_shadow_type",
- &shadow_type, NULL);
- } else {
- shadow_type = GTK_SHADOW_OUT;
- }
+
+ 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,
@@ -2197,8 +2607,7 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
switch (widget) {
case MOZ_GTK_BUTTON:
{
- /* Constant in gtkbutton.c */
- static const gint child_spacing = 1;
+ GtkBorder inner_border;
gboolean interior_focus;
gint focus_width, focus_pad;
@@ -2209,10 +2618,11 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
become too big and stuff the layout. */
if (!inhtml) {
moz_gtk_widget_get_focus(gButtonWidget, &interior_focus, &focus_width, &focus_pad);
- *left += focus_width + focus_pad + child_spacing;
- *right += focus_width + focus_pad + child_spacing;
- *top += focus_width + focus_pad + child_spacing;
- *bottom += focus_width + focus_pad + child_spacing;
+ 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;
@@ -2221,11 +2631,6 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
*bottom += gButtonWidget->style->ythickness;
return MOZ_GTK_SUCCESS;
}
-
- case MOZ_GTK_TOOLBAR:
- ensure_toolbar_widget();
- w = gToolbarWidget;
- break;
case MOZ_GTK_ENTRY:
ensure_entry_widget();
w = gEntryWidget;
@@ -2242,19 +2647,19 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
* That is why the following code is the same as for MOZ_GTK_BUTTON.
* */
- /* Constant in gtkbutton.c */
- static const gint child_spacing = 1;
+ 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);
- *left += focus_width + focus_pad;
- *right += focus_width + focus_pad;
- *top += focus_width + focus_pad + child_spacing;
- *bottom += focus_width + focus_pad + child_spacing;
+ 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;
@@ -2267,32 +2672,59 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
w = gTreeHeaderSortArrowWidget;
break;
case MOZ_GTK_DROPDOWN_ENTRY:
- ensure_dropdown_entry_widget();
- w = gDropdownEntryWidget;
+ ensure_combo_box_entry_widgets();
+ w = gComboBoxEntryTextareaWidget;
break;
case MOZ_GTK_DROPDOWN_ARROW:
- ensure_arrow_widget();
- w = gDropdownButtonWidget;
+ 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 interior_focus;
- GtkRequisition indicator_size;
- GtkBorder indicator_spacing;
- gint focus_width, focus_pad;
+ /* 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);
+ }
- ensure_option_menu_widget();
- *right = *left = gOptionMenuWidget->style->xthickness;
- *bottom = *top = gOptionMenuWidget->style->ythickness;
- moz_gtk_option_menu_get_metrics(&interior_focus, &indicator_size,
- &indicator_spacing, &focus_width, &focus_pad);
+ gtk_widget_size_request(gComboBoxArrowWidget, &arrow_req);
if (direction == GTK_TEXT_DIR_RTL)
- *left += indicator_spacing.left + indicator_size.width + indicator_spacing.right;
+ *left += separator_width + arrow_req.width;
else
- *right += indicator_spacing.left + indicator_size.width + indicator_spacing.right;
+ *right += separator_width + arrow_req.width;
+
return MOZ_GTK_SUCCESS;
}
case MOZ_GTK_TABPANELS:
@@ -2379,10 +2811,6 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
return MOZ_GTK_SUCCESS;
}
- case MOZ_GTK_MENUBAR:
- ensure_menu_bar_widget();
- w = gMenuBarWidget;
- break;
case MOZ_GTK_MENUPOPUP:
ensure_menu_popup_widget();
w = gMenuPopupWidget;
@@ -2416,6 +2844,7 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
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.*/
@@ -2425,6 +2854,10 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
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:
@@ -2439,22 +2872,48 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
}
gint
-moz_gtk_get_dropdown_arrow_size(gint* width, gint* height)
+moz_gtk_get_combo_box_entry_button_size(gint* width, gint* height)
{
- const gint min_arrow_size = 15;
- ensure_arrow_widget();
-
/*
- * First get the border of the dropdown arrow, then add in the requested
- * size of the arrow. Note that the minimum arrow size is fixed at
- * 15 pixels.
- */
+ * 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;
- *width = 2 * (1 + XTHICKNESS(gDropdownButtonWidget->style));
- *width += min_arrow_size + GTK_MISC(gArrowWidget)->xpad * 2;
+ return MOZ_GTK_SUCCESS;
+}
+
+gint
+moz_gtk_get_downarrow_size(gint* width, gint* height)
+{
+ GtkRequisition requisition;
+ ensure_button_arrow_widget();
- *height = 2 * (1 + YTHICKNESS(gDropdownButtonWidget->style));
- *height += min_arrow_size + GTK_MISC(gArrowWidget)->ypad * 2;
+ gtk_widget_size_request(gButtonArrowWidget, &requisition);
+ *width = requisition.width;
+ *height = requisition.height;
return MOZ_GTK_SUCCESS;
}
@@ -2462,18 +2921,22 @@ moz_gtk_get_dropdown_arrow_size(gint* width, gint* height)
gint
moz_gtk_get_toolbar_separator_width(gint* size)
{
- gboolean wide_separators;
- gint separator_width;
+ 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,
- "wide-separators", &wide_separators,
- "separator-width", &separator_width,
NULL);
/* Just in case... */
@@ -2507,15 +2970,16 @@ moz_gtk_get_treeview_expander_size(gint* size)
gint
moz_gtk_get_menu_separator_height(gint *size)
{
- gboolean wide_separators;
- gint separator_height;
+ gboolean wide_separators = FALSE;
+ gint separator_height = 0;
ensure_menu_separator_widget();
- gtk_widget_style_get(gMenuSeparatorWidget,
- "wide-separators", &wide_separators,
- "separator-height", &separator_height,
- NULL);
+ 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;
@@ -2559,6 +3023,19 @@ moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics *metrics)
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,
@@ -2634,7 +3111,7 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable,
break;
case MOZ_GTK_TREE_HEADER_CELL:
return moz_gtk_tree_header_cell_paint(drawable, rect, cliprect, state,
- direction);
+ flags, direction);
break;
case MOZ_GTK_TREE_HEADER_SORTARROW:
return moz_gtk_tree_header_sort_arrow_paint(drawable, rect, cliprect,
@@ -2655,18 +3132,21 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable,
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_option_menu_paint(drawable, rect, cliprect, state,
- direction);
+ return moz_gtk_combo_box_paint(drawable, rect, cliprect, state,
+ (gboolean) flags, direction);
break;
case MOZ_GTK_DROPDOWN_ARROW:
- return moz_gtk_dropdown_arrow_paint(drawable, rect, cliprect, state,
- direction);
+ return moz_gtk_combo_box_entry_button_paint(drawable, rect, cliprect,
+ state, flags, direction);
break;
case MOZ_GTK_DROPDOWN_ENTRY:
- ensure_dropdown_entry_widget();
+ ensure_combo_box_entry_widgets();
return moz_gtk_entry_paint(drawable, rect, cliprect, state,
- gDropdownEntryWidget, direction);
+ gComboBoxEntryTextareaWidget, direction);
break;
case MOZ_GTK_CHECKBUTTON_CONTAINER:
case MOZ_GTK_RADIOBUTTON_CONTAINER:
@@ -2711,6 +3191,10 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable,
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;
@@ -2766,6 +3250,8 @@ GtkWidget* moz_gtk_get_scrollbar_widget(void)
gint
moz_gtk_shutdown()
{
+ GtkWidgetClass *entry_class;
+
if (gTooltipWidget)
gtk_widget_destroy(gTooltipWidget);
/* This will destroy all of our widgets */
@@ -2775,6 +3261,7 @@ moz_gtk_shutdown()
gProtoWindow = NULL;
gButtonWidget = NULL;
gToggleButtonWidget = NULL;
+ gButtonArrowWidget = NULL;
gCheckboxWidget = NULL;
gRadiobuttonWidget = NULL;
gHorizScrollbarWidget = NULL;
@@ -2783,11 +3270,14 @@ moz_gtk_shutdown()
gHScaleWidget = NULL;
gVScaleWidget = NULL;
gEntryWidget = NULL;
- gArrowWidget = NULL;
- gOptionMenuWidget = NULL;
- gDropdownButtonWidget = NULL;
- gDropdownEntryWidget = NULL;
+ gComboBoxWidget = NULL;
+ gComboBoxButtonWidget = NULL;
+ gComboBoxSeparatorWidget = NULL;
+ gComboBoxArrowWidget = NULL;
gComboBoxEntryWidget = NULL;
+ gComboBoxEntryButtonWidget = NULL;
+ gComboBoxEntryArrowWidget = NULL;
+ gComboBoxEntryTextareaWidget = NULL;
gHandleBoxWidget = NULL;
gToolbarWidget = NULL;
gStatusbarWidget = NULL;
@@ -2799,8 +3289,10 @@ moz_gtk_shutdown()
gMenuBarItemWidget = NULL;
gMenuPopupWidget = NULL;
gMenuItemWidget = NULL;
+ gImageMenuItemWidget = NULL;
gCheckMenuItemWidget = NULL;
gTreeViewWidget = NULL;
+ gMiddleTreeViewColumn = NULL;
gTreeHeaderCellWidget = NULL;
gTreeHeaderSortArrowWidget = NULL;
gExpanderWidget = NULL;
@@ -2808,6 +3300,10 @@ moz_gtk_shutdown()
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;
diff --git a/WebCore/platform/gtk/gtkdrawing.h b/WebCore/platform/gtk/gtkdrawing.h
index ee79746..6e44d4a 100644
--- a/WebCore/platform/gtk/gtkdrawing.h
+++ b/WebCore/platform/gtk/gtkdrawing.h
@@ -144,6 +144,8 @@ typedef enum {
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). */
@@ -176,6 +178,8 @@ typedef enum {
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 */
@@ -289,6 +293,16 @@ moz_gtk_checkbox_get_metrics(gint* indicator_size, gint* indicator_spacing);
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
@@ -329,7 +343,25 @@ moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics* metrics);
*
* returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
*/
-gint moz_gtk_get_dropdown_arrow_size(gint* width, gint* height);
+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
@@ -383,6 +415,12 @@ GtkWidget* moz_gtk_get_scrollbar_widget(void);
*/
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 */
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 */