summaryrefslogtreecommitdiffstats
path: root/WebKitTools/DumpRenderTree
diff options
context:
space:
mode:
Diffstat (limited to 'WebKitTools/DumpRenderTree')
-rw-r--r--WebKitTools/DumpRenderTree/AccessibilityUIElement.cpp10
-rw-r--r--WebKitTools/DumpRenderTree/AccessibilityUIElement.h2
-rw-r--r--WebKitTools/DumpRenderTree/DumpRenderTree.gypi10
-rw-r--r--WebKitTools/DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj8
-rw-r--r--WebKitTools/DumpRenderTree/chromium/EventSender.cpp3
-rw-r--r--WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp6
-rw-r--r--WebKitTools/DumpRenderTree/chromium/TestShellWin.cpp7
-rwxr-xr-xWebKitTools/DumpRenderTree/chromium/WebThemeControlDRT.cpp518
-rwxr-xr-xWebKitTools/DumpRenderTree/chromium/WebThemeControlDRT.h202
-rwxr-xr-xWebKitTools/DumpRenderTree/chromium/WebThemeEngineDRT.cpp674
-rwxr-xr-xWebKitTools/DumpRenderTree/chromium/WebThemeEngineDRT.h93
-rw-r--r--WebKitTools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp6
-rw-r--r--WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp18
-rw-r--r--WebKitTools/DumpRenderTree/gtk/EventSender.cpp384
-rw-r--r--WebKitTools/DumpRenderTree/gtk/EventSender.h2
-rw-r--r--WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm11
-rw-r--r--WebKitTools/DumpRenderTree/mac/Configurations/Base.xcconfig1
-rw-r--r--WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm8
-rw-r--r--WebKitTools/DumpRenderTree/mac/EventSendingController.mm31
-rw-r--r--WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm11
-rw-r--r--WebKitTools/DumpRenderTree/mac/MockGeolocationProvider.h47
-rw-r--r--WebKitTools/DumpRenderTree/mac/MockGeolocationProvider.mm109
-rw-r--r--WebKitTools/DumpRenderTree/mac/UIDelegate.mm11
-rw-r--r--WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp62
-rw-r--r--WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.h23
-rw-r--r--WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp72
-rw-r--r--WebKitTools/DumpRenderTree/qt/EventSenderQt.h8
-rw-r--r--WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp23
-rw-r--r--WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h11
-rw-r--r--WebKitTools/DumpRenderTree/win/AccessibilityUIElementWin.cpp6
-rw-r--r--WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp4
31 files changed, 2106 insertions, 275 deletions
diff --git a/WebKitTools/DumpRenderTree/AccessibilityUIElement.cpp b/WebKitTools/DumpRenderTree/AccessibilityUIElement.cpp
index 9cf34de..c4d5e6f 100644
--- a/WebKitTools/DumpRenderTree/AccessibilityUIElement.cpp
+++ b/WebKitTools/DumpRenderTree/AccessibilityUIElement.cpp
@@ -171,6 +171,15 @@ static JSValueRef childAtIndexCallback(JSContextRef context, JSObjectRef functio
return AccessibilityUIElement::makeJSAccessibilityUIElement(context, toAXElement(thisObject)->getChildAtIndex(indexNumber));
}
+static JSValueRef linkedUIElementAtIndexCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ int indexNumber = -1;
+ if (argumentCount == 1)
+ indexNumber = JSValueToNumber(context, arguments[0], exception);
+
+ return AccessibilityUIElement::makeJSAccessibilityUIElement(context, toAXElement(thisObject)->linkedUIElementAtIndex(indexNumber));
+}
+
static JSValueRef disclosedRowAtIndexCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
int indexNumber = 0;
@@ -703,6 +712,7 @@ JSClassRef AccessibilityUIElement::getJSClass()
{ "boundsForRange", boundsForRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "stringForRange", stringForRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "childAtIndex", childAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "linkedUIElementAtIndex", linkedUIElementAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "indexOfChild", indexOfChildCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "elementAtPoint", elementAtPointCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "attributesOfColumnHeaders", attributesOfColumnHeadersCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
diff --git a/WebKitTools/DumpRenderTree/AccessibilityUIElement.h b/WebKitTools/DumpRenderTree/AccessibilityUIElement.h
index f62ec1a..2a06962 100644
--- a/WebKitTools/DumpRenderTree/AccessibilityUIElement.h
+++ b/WebKitTools/DumpRenderTree/AccessibilityUIElement.h
@@ -91,6 +91,8 @@ public:
// Methods - platform-independent implementations
JSStringRef allAttributes();
JSStringRef attributesOfLinkedUIElements();
+ AccessibilityUIElement linkedUIElementAtIndex(unsigned);
+
JSStringRef attributesOfDocumentLinks();
JSStringRef attributesOfChildren();
JSStringRef parameterizedAttributeNames();
diff --git a/WebKitTools/DumpRenderTree/DumpRenderTree.gypi b/WebKitTools/DumpRenderTree/DumpRenderTree.gypi
index 280c8dd..5fc8dab 100644
--- a/WebKitTools/DumpRenderTree/DumpRenderTree.gypi
+++ b/WebKitTools/DumpRenderTree/DumpRenderTree.gypi
@@ -34,5 +34,15 @@
'chromium/WebViewHost.cpp',
'chromium/WebViewHost.h',
],
+ 'conditions': [
+ ['OS=="win"', {
+ 'drt_files': [
+ 'chromium/WebThemeControlDRT.cpp',
+ 'chromium/WebThemeControlDRT.h',
+ 'chromium/WebThemeEngineDRT.cpp',
+ 'chromium/WebThemeEngineDRT.h',
+ ],
+ }],
+ ],
}
}
diff --git a/WebKitTools/DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj b/WebKitTools/DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj
index 3adfaf2..6a49b44 100644
--- a/WebKitTools/DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj
+++ b/WebKitTools/DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj
@@ -117,6 +117,8 @@
BCD08B3A0E1057EF00A7D0C1 /* AccessibilityController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCD08B390E1057EF00A7D0C1 /* AccessibilityController.cpp */; };
BCD08B710E1059D200A7D0C1 /* AccessibilityControllerMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BCD08B700E1059D200A7D0C1 /* AccessibilityControllerMac.mm */; };
BCF6C6500C98E9C000AC063E /* GCController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCF6C64F0C98E9C000AC063E /* GCController.cpp */; };
+ E1B7816511AF31B7007E1BC2 /* MockGeolocationProvider.mm in Sources */ = {isa = PBXBuildFile; fileRef = E1B7808711AF1669007E1BC2 /* MockGeolocationProvider.mm */; };
+ E1B7816711AF31C3007E1BC2 /* MockGeolocationProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = E1B7808511AF1643007E1BC2 /* MockGeolocationProvider.h */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -275,6 +277,8 @@
BCD08B390E1057EF00A7D0C1 /* AccessibilityController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AccessibilityController.cpp; sourceTree = "<group>"; };
BCD08B700E1059D200A7D0C1 /* AccessibilityControllerMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AccessibilityControllerMac.mm; path = mac/AccessibilityControllerMac.mm; sourceTree = "<group>"; };
BCF6C64F0C98E9C000AC063E /* GCController.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 30; path = GCController.cpp; sourceTree = "<group>"; };
+ E1B7808511AF1643007E1BC2 /* MockGeolocationProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MockGeolocationProvider.h; path = mac/MockGeolocationProvider.h; sourceTree = "<group>"; };
+ E1B7808711AF1669007E1BC2 /* MockGeolocationProvider.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MockGeolocationProvider.mm; path = mac/MockGeolocationProvider.mm; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -378,6 +382,8 @@
BC0131D80C9772010087317D /* LayoutTestController.cpp */,
BC0131D90C9772010087317D /* LayoutTestController.h */,
BCA18B220C9B014B00114369 /* LayoutTestControllerMac.mm */,
+ E1B7808511AF1643007E1BC2 /* MockGeolocationProvider.h */,
+ E1B7808711AF1669007E1BC2 /* MockGeolocationProvider.mm */,
BCA18B6D0C9B08DB00114369 /* NavigationController.h */,
BCA18B6E0C9B08DB00114369 /* NavigationController.m */,
BCA18B2F0C9B01B400114369 /* ObjCController.h */,
@@ -546,6 +552,7 @@
BC9D90250C97472E0099A4A3 /* WorkQueue.h in Headers */,
BC9D90260C97472E0099A4A3 /* WorkQueueItem.h in Headers */,
5185F6B310714E12007AA393 /* HistoryDelegate.h in Headers */,
+ E1B7816711AF31C3007E1BC2 /* MockGeolocationProvider.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -712,6 +719,7 @@
BC9D90240C97472E0099A4A3 /* WorkQueue.cpp in Sources */,
BCA18B260C9B015C00114369 /* WorkQueueItemMac.mm in Sources */,
5185F6B210714E07007AA393 /* HistoryDelegate.mm in Sources */,
+ E1B7816511AF31B7007E1BC2 /* MockGeolocationProvider.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/WebKitTools/DumpRenderTree/chromium/EventSender.cpp b/WebKitTools/DumpRenderTree/chromium/EventSender.cpp
index 381112e..7695095 100644
--- a/WebKitTools/DumpRenderTree/chromium/EventSender.cpp
+++ b/WebKitTools/DumpRenderTree/chromium/EventSender.cpp
@@ -716,8 +716,7 @@ void EventSender::replaySavedEvents()
{
replayingSavedEvents = true;
while (!mouseEventQueue.isEmpty()) {
- SavedEvent e = mouseEventQueue.first();
- mouseEventQueue.removeFirst();
+ SavedEvent e = mouseEventQueue.takeFirst();
switch (e.type) {
case SavedEvent::MouseMove: {
diff --git a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp
index b4e3764..89e16e0 100644
--- a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp
+++ b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp
@@ -201,8 +201,7 @@ void LayoutTestController::WorkQueue::processWork()
// Quit doing work once a load is in progress.
while (!m_queue.isEmpty()) {
bool startedLoad = m_queue.first()->run(shell);
- delete m_queue.first();
- m_queue.removeFirst();
+ delete m_queue.takeFirst();
if (startedLoad)
return;
}
@@ -215,8 +214,7 @@ void LayoutTestController::WorkQueue::reset()
{
m_frozen = false;
while (!m_queue.isEmpty()) {
- delete m_queue.first();
- m_queue.removeFirst();
+ delete m_queue.takeFirst();
}
}
diff --git a/WebKitTools/DumpRenderTree/chromium/TestShellWin.cpp b/WebKitTools/DumpRenderTree/chromium/TestShellWin.cpp
index 3884e94..a9ca6a9 100644
--- a/WebKitTools/DumpRenderTree/chromium/TestShellWin.cpp
+++ b/WebKitTools/DumpRenderTree/chromium/TestShellWin.cpp
@@ -31,6 +31,7 @@
#include "config.h"
#include "TestShell.h"
+#include "WebThemeEngineDRT.h"
#include "webkit/support/webkit_support.h"
#include <fcntl.h>
#include <io.h>
@@ -38,6 +39,9 @@
#include <shlwapi.h>
#include <sys/stat.h>
+// Theme engine
+static WebThemeEngineDRT themeEngine;
+
// Thread main to run for the thread which just tests for timeout.
unsigned int __stdcall watchDogThread(void* arg)
{
@@ -105,6 +109,9 @@ void platformInit()
_setmode(_fileno(stdout), _O_BINARY);
_setmode(_fileno(stderr), _O_BINARY);
+ // Set theme engine.
+ webkit_support::SetThemeEngine(&themeEngine);
+
// Load Ahem font.
// AHEM____.TTF is copied to the directory of DumpRenderTree.exe by WebKit.gyp.
WCHAR path[_MAX_PATH];
diff --git a/WebKitTools/DumpRenderTree/chromium/WebThemeControlDRT.cpp b/WebKitTools/DumpRenderTree/chromium/WebThemeControlDRT.cpp
new file mode 100755
index 0000000..df12476
--- /dev/null
+++ b/WebKitTools/DumpRenderTree/chromium/WebThemeControlDRT.cpp
@@ -0,0 +1,518 @@
+/*
+ * Copyright (C) 2010 Google 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:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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.
+ */
+
+// This file implements a simple generic version of the WebThemeEngine,
+// which is used to draw all the native controls on a web page. We use this
+// file when running in layout test mode in order to remove any
+// platform-specific rendering differences due to themes, colors, etc.
+//
+
+#include "config.h"
+#include "WebThemeControlDRT.h"
+
+#include "skia/ext/platform_canvas.h"
+#include "skia/ext/skia_utils_win.h"
+#include "third_party/skia/include/core/SkPaint.h"
+#include "third_party/skia/include/core/SkPath.h"
+#include "third_party/skia/include/core/SkRect.h"
+
+#include <wtf/Assertions.h>
+
+using namespace std;
+using namespace skia;
+
+static const SkColor edgeColor = SK_ColorBLACK;
+static const SkColor readOnlyColor = SkColorSetRGB(0xe9, 0xc2, 0xa6);
+static const SkColor fgColor = SK_ColorBLACK;
+static const SkColor bgColors[] = {
+ SK_ColorBLACK, // Unknown
+ SkColorSetRGB(0xc9, 0xc9, 0xc9), // Disabled
+ SkColorSetRGB(0xf3, 0xe0, 0xd0), // Readonly
+ SkColorSetRGB(0x89, 0xc4, 0xff), // Normal
+ SkColorSetRGB(0x43, 0xf9, 0xff), // Hot
+ SkColorSetRGB(0x20, 0xf6, 0xcc), // Focused
+ SkColorSetRGB(0x00, 0xf3, 0xac), // Hover
+ SkColorSetRGB(0xa9, 0xff, 0x12), // Pressed
+ SkColorSetRGB(0xcc, 0xcc, 0xcc) // Indeterminate
+};
+
+static SkIRect validate(const SkIRect& rect, WebThemeControlDRT::Type ctype)
+{
+ switch (ctype) {
+ case WebThemeControlDRT::UncheckedBoxType:
+ case WebThemeControlDRT::CheckedBoxType:
+ case WebThemeControlDRT::UncheckedRadioType:
+ case WebThemeControlDRT::CheckedRadioType: {
+ SkIRect retval = rect;
+
+ // The maximum width and height is 13.
+ // Center the square in the passed rectangle.
+ const int maxControlSize = 13;
+ int controlSize = min(rect.width(), rect.height());
+ controlSize = min(controlSize, maxControlSize);
+
+ retval.fLeft = rect.fLeft + (rect.width() / 2) - (controlSize / 2);
+ retval.fRight = retval.fLeft + controlSize - 1;
+ retval.fTop = rect.fTop + (rect.height() / 2) - (controlSize / 2);
+ retval.fBottom = retval.fTop + controlSize - 1;
+
+ return retval;
+ }
+
+ default:
+ return rect;
+ }
+}
+
+// WebThemeControlDRT
+
+WebThemeControlDRT::WebThemeControlDRT(PlatformCanvas* canvas,
+ const SkIRect& irect,
+ Type ctype,
+ State cstate)
+ : m_canvas(canvas)
+ , m_irect(validate(irect, ctype))
+ , m_type(ctype)
+ , m_state(cstate)
+ , m_left(m_irect.fLeft)
+ , m_right(m_irect.fRight)
+ , m_top(m_irect.fTop)
+ , m_bottom(m_irect.fBottom)
+ , m_height(m_irect.height())
+ , m_width(m_irect.width())
+ , m_edgeColor(edgeColor)
+ , m_bgColor(bgColors[cstate])
+ , m_fgColor(fgColor)
+{
+}
+
+WebThemeControlDRT::~WebThemeControlDRT()
+{
+}
+
+void WebThemeControlDRT::box(const SkIRect& rect, SkColor fillColor)
+{
+ SkPaint paint;
+
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setColor(fillColor);
+ m_canvas->drawIRect(rect, paint);
+
+ paint.setColor(m_edgeColor);
+ paint.setStyle(SkPaint::kStroke_Style);
+ m_canvas->drawIRect(rect, paint);
+}
+
+void WebThemeControlDRT::line(int x0, int y0, int x1, int y1, SkColor color)
+{
+ SkPaint paint;
+ paint.setColor(color);
+ m_canvas->drawLine(SkIntToScalar(x0), SkIntToScalar(y0),
+ SkIntToScalar(x1), SkIntToScalar(y1),
+ paint);
+}
+
+void WebThemeControlDRT::triangle(int x0, int y0,
+ int x1, int y1,
+ int x2, int y2,
+ SkColor color)
+{
+ SkPath path;
+ SkPaint paint;
+
+ paint.setColor(color);
+ paint.setStyle(SkPaint::kFill_Style);
+ path.incReserve(4);
+ path.moveTo(SkIntToScalar(x0), SkIntToScalar(y0));
+ path.lineTo(SkIntToScalar(x1), SkIntToScalar(y1));
+ path.lineTo(SkIntToScalar(x2), SkIntToScalar(y2));
+ path.close();
+ m_canvas->drawPath(path, paint);
+
+ paint.setColor(m_edgeColor);
+ paint.setStyle(SkPaint::kStroke_Style);
+ m_canvas->drawPath(path, paint);
+}
+
+void WebThemeControlDRT::roundRect(SkColor color)
+{
+ SkRect rect;
+ SkScalar radius = SkIntToScalar(5);
+ SkPaint paint;
+
+ rect.set(m_irect);
+ paint.setColor(color);
+ paint.setStyle(SkPaint::kFill_Style);
+ m_canvas->drawRoundRect(rect, radius, radius, paint);
+
+ paint.setColor(m_edgeColor);
+ paint.setStyle(SkPaint::kStroke_Style);
+ m_canvas->drawRoundRect(rect, radius, radius, paint);
+}
+
+void WebThemeControlDRT::oval(SkColor color)
+{
+ SkRect rect;
+ SkPaint paint;
+
+ rect.set(m_irect);
+ paint.setColor(color);
+ paint.setStyle(SkPaint::kFill_Style);
+ m_canvas->drawOval(rect, paint);
+
+ paint.setColor(m_edgeColor);
+ paint.setStyle(SkPaint::kStroke_Style);
+ m_canvas->drawOval(rect, paint);
+}
+
+void WebThemeControlDRT::circle(SkScalar radius, SkColor color)
+{
+ SkScalar cy = SkIntToScalar(m_top + m_height / 2);
+ SkScalar cx = SkIntToScalar(m_left + m_width / 2);
+ SkPaint paint;
+
+ paint.setColor(color);
+ paint.setStyle(SkPaint::kFill_Style);
+ m_canvas->drawCircle(cx, cy, radius, paint);
+
+ paint.setColor(m_edgeColor);
+ paint.setStyle(SkPaint::kStroke_Style);
+ m_canvas->drawCircle(cx, cy, radius, paint);
+}
+
+void WebThemeControlDRT::nestedBoxes(int indentLeft,
+ int indentTop,
+ int indentRight,
+ int indentBottom,
+ SkColor outerColor,
+ SkColor innerColor)
+{
+ SkIRect lirect;
+ box(m_irect, outerColor);
+ lirect.set(m_irect.fLeft + indentLeft,
+ m_irect.fTop + indentTop,
+ m_irect.fRight - indentRight,
+ m_irect.fBottom - indentBottom);
+ box(lirect, innerColor);
+}
+
+void WebThemeControlDRT::markState()
+{
+ // The horizontal lines in a read only control are spaced by this amount.
+ const int readOnlyLineOffset = 5;
+
+ // The length of a triangle side for the corner marks.
+ const int triangleSize = 5;
+
+ switch (m_state) {
+ case UnknownState:
+ case DisabledState:
+ case NormalState:
+ // Don't visually mark these states (color is enough).
+ break;
+ case ReadOnlyState:
+ // Drawing lines across the control.
+ for (int i = m_top + readOnlyLineOffset; i < m_bottom; i += readOnlyLineOffset)
+ line(m_left + 1, i, m_right - 1, i, readOnlyColor);
+ break;
+
+ case HotState:
+ // Draw a triangle in the upper left corner of the control.
+ triangle(m_left, m_top,
+ m_left + triangleSize, m_top,
+ m_left, m_top + triangleSize, m_edgeColor);
+ break;
+
+ case HoverState:
+ // Draw a triangle in the upper right corner of the control.
+ triangle(m_right, m_top,
+ m_right, m_top + triangleSize,
+ m_right - triangleSize, m_top, m_edgeColor);
+ break;
+
+ case FocusedState:
+ // Draw a triangle in the bottom right corner of the control.
+ triangle(m_right, m_bottom,
+ m_right - triangleSize, m_bottom,
+ m_right, m_bottom - triangleSize, m_edgeColor);
+ break;
+
+ case PressedState:
+ // Draw a triangle in the bottom left corner of the control.
+ triangle(m_left, m_bottom,
+ m_left, m_bottom - triangleSize,
+ m_left + triangleSize, m_bottom, m_edgeColor);
+ break;
+
+ default:
+ ASSERT_NOT_REACHED();
+ CRASH();
+ break;
+ }
+}
+
+void WebThemeControlDRT::draw()
+{
+ int halfWidth = m_width / 2;
+ int halfHeight = m_height / 2;
+ int quarterWidth = m_width / 4;
+ int quarterHeight = m_height / 4;
+
+ // Indent amounts for the check in a checkbox or radio button.
+ const int checkIndent = 3;
+
+ // Indent amounts for short and long sides of the scrollbar notches.
+ const int notchLongOffset = 1;
+ const int notchShortOffset = 4;
+ const int noOffset = 0;
+
+ // Indent amounts for the short and long sides of a scroll thumb box.
+ const int thumbLongIndent = 0;
+ const int thumbShortIndent = 2;
+
+ // Indents for the crosshatch on a scroll grip.
+ const int gripLongIndent = 3;
+ const int gripShortIndent = 5;
+
+ // Indents for the the slider track.
+ const int sliderIndent = 2;
+
+ m_canvas->beginPlatformPaint();
+
+ switch (m_type) {
+ case UnknownType:
+ ASSERT_NOT_REACHED();
+ CRASH();
+ break;
+
+ case TextFieldType:
+ // We render this by hand outside of this function.
+ ASSERT_NOT_REACHED();
+ CRASH();
+ break;
+
+ case PushButtonType:
+ // push buttons render as a rounded rectangle
+ roundRect(m_bgColor);
+ break;
+
+ case UncheckedBoxType:
+ // Unchecked boxes are simply plain boxes.
+ box(m_irect, m_bgColor);
+ break;
+
+ case CheckedBoxType:
+ nestedBoxes(checkIndent, checkIndent, checkIndent, checkIndent, m_bgColor, m_fgColor);
+ break;
+
+ case UncheckedRadioType:
+ circle(SkIntToScalar(halfHeight), m_bgColor);
+ break;
+
+ case CheckedRadioType:
+ circle(SkIntToScalar(halfHeight), m_bgColor);
+ circle(SkIntToScalar(halfHeight - checkIndent), m_fgColor);
+ break;
+
+ case HorizontalScrollTrackBackType: {
+ // Draw a box with a notch at the left.
+ int longOffset = halfHeight - notchLongOffset;
+ int shortOffset = m_width - notchShortOffset;
+ nestedBoxes(noOffset, longOffset, shortOffset, longOffset, m_bgColor, m_edgeColor);
+ break;
+ }
+
+ case HorizontalScrollTrackForwardType: {
+ // Draw a box with a notch at the right.
+ int longOffset = halfHeight - notchLongOffset;
+ int shortOffset = m_width - notchShortOffset;
+ nestedBoxes(shortOffset, longOffset, noOffset, longOffset, m_bgColor, m_fgColor);
+ break;
+ }
+
+ case VerticalScrollTrackBackType: {
+ // Draw a box with a notch at the top.
+ int longOffset = halfWidth - notchLongOffset;
+ int shortOffset = m_height - notchShortOffset;
+ nestedBoxes(longOffset, noOffset, longOffset, shortOffset, m_bgColor, m_fgColor);
+ break;
+ }
+
+ case VerticalScrollTrackForwardType: {
+ // Draw a box with a notch at the bottom.
+ int longOffset = halfWidth - notchLongOffset;
+ int shortOffset = m_height - notchShortOffset;
+ nestedBoxes(longOffset, shortOffset, longOffset, noOffset, m_bgColor, m_fgColor);
+ break;
+ }
+
+ case HorizontalScrollThumbType:
+ // Draw a narrower box on top of the outside box.
+ nestedBoxes(thumbLongIndent, thumbShortIndent, thumbLongIndent, thumbShortIndent, m_bgColor, m_bgColor);
+ break;
+
+ case VerticalScrollThumbType:
+ // Draw a shorter box on top of the outside box.
+ nestedBoxes(thumbShortIndent, thumbLongIndent, thumbShortIndent, thumbLongIndent, m_bgColor, m_bgColor);
+ break;
+
+ case HorizontalSliderThumbType:
+ // Slider thumbs are ovals.
+ oval(m_bgColor);
+ break;
+
+ case HorizontalScrollGripType: {
+ // Draw a horizontal crosshatch for the grip.
+ int longOffset = halfWidth - gripLongIndent;
+ line(m_left + gripLongIndent, m_top + halfHeight,
+ m_right - gripLongIndent, m_top + halfHeight, m_fgColor);
+ line(m_left + longOffset, m_top + gripShortIndent,
+ m_left + longOffset, m_bottom - gripShortIndent, m_fgColor);
+ line(m_right - longOffset, m_top + gripShortIndent,
+ m_right - longOffset, m_bottom - gripShortIndent, m_fgColor);
+ break;
+ }
+
+ case VerticalScrollGripType: {
+ // Draw a vertical crosshatch for the grip.
+ int longOffset = halfHeight - gripLongIndent;
+ line(m_left + halfWidth, m_top + gripLongIndent,
+ m_left + halfWidth, m_bottom - gripLongIndent, m_fgColor);
+ line(m_left + gripShortIndent, m_top + longOffset,
+ m_right - gripShortIndent, m_top + longOffset, m_fgColor);
+ line(m_left + gripShortIndent, m_bottom - longOffset,
+ m_right - gripShortIndent, m_bottom - longOffset, m_fgColor);
+ break;
+ }
+
+ case LeftArrowType:
+ // Draw a left arrow inside a box.
+ box(m_irect, m_bgColor);
+ triangle(m_right - quarterWidth, m_top + quarterHeight,
+ m_right - quarterWidth, m_bottom - quarterHeight,
+ m_left + quarterWidth, m_top + halfHeight, m_fgColor);
+ break;
+
+ case RightArrowType:
+ // Draw a left arrow inside a box.
+ box(m_irect, m_bgColor);
+ triangle(m_left + quarterWidth, m_top + quarterHeight,
+ m_right - quarterWidth, m_top + halfHeight,
+ m_left + quarterWidth, m_bottom - quarterHeight, m_fgColor);
+ break;
+
+ case UpArrowType:
+ // Draw an up arrow inside a box.
+ box(m_irect, m_bgColor);
+ triangle(m_left + quarterWidth, m_bottom - quarterHeight,
+ m_left + halfWidth, m_top + quarterHeight,
+ m_right - quarterWidth, m_bottom - quarterHeight, m_fgColor);
+ break;
+
+ case DownArrowType:
+ // Draw a down arrow inside a box.
+ box(m_irect, m_bgColor);
+ triangle(m_left + quarterWidth, m_top + quarterHeight,
+ m_right - quarterWidth, m_top + quarterHeight,
+ m_left + halfWidth, m_bottom - quarterHeight, m_fgColor);
+ break;
+
+ case HorizontalSliderTrackType: {
+ // Draw a narrow rect for the track plus box hatches on the ends.
+ SkIRect lirect;
+ lirect = m_irect;
+ lirect.inset(noOffset, halfHeight - sliderIndent);
+ box(lirect, m_bgColor);
+ line(m_left, m_top, m_left, m_bottom, m_edgeColor);
+ line(m_right, m_top, m_right, m_bottom, m_edgeColor);
+ break;
+ }
+
+ case DropDownButtonType:
+ // Draw a box with a big down arrow on top.
+ box(m_irect, m_bgColor);
+ triangle(m_left + quarterWidth, m_top,
+ m_right - quarterWidth, m_top,
+ m_left + halfWidth, m_bottom, m_fgColor);
+ break;
+
+ default:
+ ASSERT_NOT_REACHED();
+ CRASH();
+ break;
+ }
+
+ markState();
+ m_canvas->endPlatformPaint();
+}
+
+// Because rendering a text field is dependent on input
+// parameters the other controls don't have, we render it directly
+// rather than trying to overcomplicate draw() further.
+void WebThemeControlDRT::drawTextField(bool drawEdges, bool fillContentArea, SkColor color)
+{
+ SkPaint paint;
+
+ m_canvas->beginPlatformPaint();
+ if (fillContentArea) {
+ paint.setColor(color);
+ paint.setStyle(SkPaint::kFill_Style);
+ m_canvas->drawIRect(m_irect, paint);
+ }
+ if (drawEdges) {
+ paint.setColor(m_edgeColor);
+ paint.setStyle(SkPaint::kStroke_Style);
+ m_canvas->drawIRect(m_irect, paint);
+ }
+
+ markState();
+ m_canvas->endPlatformPaint();
+}
+
+void WebThemeControlDRT::drawProgressBar(const SkIRect& fillRect)
+{
+ SkPaint paint;
+
+ m_canvas->beginPlatformPaint();
+ paint.setColor(m_bgColor);
+ paint.setStyle(SkPaint::kFill_Style);
+ m_canvas->drawIRect(m_irect, paint);
+
+ // Emulate clipping
+ SkIRect tofill;
+ tofill.intersect(m_irect, fillRect);
+ paint.setColor(m_fgColor);
+ paint.setStyle(SkPaint::kFill_Style);
+ m_canvas->drawIRect(tofill, paint);
+
+ markState();
+ m_canvas->endPlatformPaint();
+}
+
diff --git a/WebKitTools/DumpRenderTree/chromium/WebThemeControlDRT.h b/WebKitTools/DumpRenderTree/chromium/WebThemeControlDRT.h
new file mode 100755
index 0000000..1f73610
--- /dev/null
+++ b/WebKitTools/DumpRenderTree/chromium/WebThemeControlDRT.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2010 Google 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:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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.
+ */
+
+// WebThemeControlDRT implements the generic rendering of controls
+// needed by WebThemeEngineDRT. See the comments in that class
+// header file for why this class is needed and used.
+//
+// This class implements a generic set of widgets using Skia. The widgets
+// are optimized for testability, not a pleasing appearance.
+//
+
+#ifndef WebThemeControlDRT_h
+#define WebThemeControlDRT_h
+
+#include "skia/ext/platform_canvas.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include <wtf/Noncopyable.h>
+
+// Skia forward declarations
+struct SkIRect;
+
+class WebThemeControlDRT : public Noncopyable {
+public:
+ // This list of states mostly mirrors the list in WebCore/platform/ThemeTypes.h
+ // but is maintained separately since that isn't public and also to minimize
+ // dependencies.
+ // Note that the WebKit ThemeTypes seem to imply that a control can be
+ // in multiple states simultaneously but WebThemeEngine only allows for
+ // a single state at a time.
+ //
+ // Some definitions for the various states:
+ // Disabled - indicates that a control can't be modified or selected
+ // (corresponds to HTML 'disabled' attribute)
+ // ReadOnly - indicates that a control can't be modified but can be
+ // selected
+ // Normal - the normal state of control on the page when it isn't
+ // focused or otherwise active
+ // Hot - when the mouse is hovering over a part of the control,
+ // all the other parts are considered "hot"
+ // Hover - when the mouse is directly over a control (the CSS
+ // :hover pseudo-class)
+ // Focused - when the control has the keyboard focus
+ // Pressed - when the control is being triggered (by a mousedown or
+ // a key event).
+ // Indeterminate - when set to indeterminate (only for progress bar)
+ enum State {
+ UnknownState = 0,
+ DisabledState,
+ ReadOnlyState,
+ NormalState,
+ HotState,
+ HoverState,
+ FocusedState,
+ PressedState,
+ IndeterminateState
+ };
+
+ // This list of types mostly mirrors the list in
+ // WebCore/platform/ThemeTypes.h but is maintained
+ // separately since that isn't public and also to minimize dependencies.
+ //
+ // Note that what the user might think of as a single control can be
+ // made up of multiple parts. For example, a single scroll bar contains
+ // six clickable parts - two arrows, the "thumb" indicating the current
+ // position on the bar, the other two parts of the bar (before and after
+ // the thumb) and the "gripper" on the thumb itself.
+ //
+ enum Type {
+ UnknownType = 0,
+ TextFieldType,
+ PushButtonType,
+ UncheckedBoxType,
+ CheckedBoxType,
+ UncheckedRadioType,
+ CheckedRadioType,
+ HorizontalScrollTrackBackType,
+ HorizontalScrollTrackForwardType,
+ HorizontalScrollThumbType,
+ HorizontalScrollGripType,
+ VerticalScrollTrackBackType,
+ VerticalScrollTrackForwardType,
+ VerticalScrollThumbType,
+ VerticalScrollGripType,
+ LeftArrowType,
+ RightArrowType,
+ UpArrowType,
+ DownArrowType,
+ HorizontalSliderTrackType,
+ HorizontalSliderThumbType,
+ DropDownButtonType,
+ ProgressBarType
+ };
+
+ // canvas is the canvas to draw onto, and rect gives the size of the
+ // control. ctype and cstate specify the type and state of the control.
+ WebThemeControlDRT(skia::PlatformCanvas* canvas,
+ const SkIRect& rect,
+ Type ctype,
+ State cstate);
+ ~WebThemeControlDRT();
+
+ // Draws the control.
+ void draw();
+
+ // Use this for TextField controls instead, because the logic
+ // for drawing them is dependent on what WebKit tells us to do.
+ // If drawEdges is true, draw an edge around the control. If
+ // fillContentArea is true, fill the content area with the given color.
+ void drawTextField(bool drawEdges, bool fillContentArea, SkColor color);
+
+ // Use this for drawing ProgressBar controls instead, since we
+ // need to know the rect to fill inside the bar.
+ void drawProgressBar(const SkIRect& fillRect);
+
+private:
+ // Draws a box of size specified by irect, filled with the given color.
+ // The box will have a border drawn in the default edge color.
+ void box(const SkIRect& irect, SkColor color);
+
+
+ // Draws a triangle of size specified by the three pairs of coordinates,
+ // filled with the given color. The box will have an edge drawn in the
+ // default edge color.
+ void triangle(int x0, int y0, int x1, int y1, int x2, int y2, SkColor color);
+
+ // Draws a rectangle the size of the control with rounded corners, filled
+ // with the specified color (and with a border in the default edge color).
+ void roundRect(SkColor color);
+
+ // Draws an oval the size of the control, filled with the specified color
+ // and with a border in the default edge color.
+ void oval(SkColor color);
+
+ // Draws a circle centered in the control with the specified radius,
+ // filled with the specified color, and with a border draw in the
+ // default edge color.
+ void circle(SkScalar radius, SkColor color);
+
+ // Draws a box the size of the control, filled with the outerColor and
+ // with a border in the default edge color, and then draws another box
+ // indented on all four sides by the specified amounts, filled with the
+ // inner color and with a border in the default edge color.
+ void nestedBoxes(int indentLeft,
+ int indentTop,
+ int indentRight,
+ int indentBottom,
+ SkColor outerColor,
+ SkColor innerColor);
+
+ // Draws a line between the two points in the given color.
+ void line(int x0, int y0, int x1, int y1, SkColor color);
+
+ // Draws a distinctive mark on the control for each state, so that the
+ // state of the control can be determined without needing to know which
+ // color is which.
+ void markState();
+
+ skia::PlatformCanvas* m_canvas;
+ const SkIRect m_irect;
+ const Type m_type;
+ const State m_state;
+ const SkColor m_edgeColor;
+ const SkColor m_bgColor;
+ const SkColor m_fgColor;
+
+ // The following are convenience accessors for m_irect.
+ const int m_left;
+ const int m_right;
+ const int m_top;
+ const int m_bottom;
+ const int m_width;
+ const int m_height;
+};
+
+#endif // WebThemeControlDRT_h
diff --git a/WebKitTools/DumpRenderTree/chromium/WebThemeEngineDRT.cpp b/WebKitTools/DumpRenderTree/chromium/WebThemeEngineDRT.cpp
new file mode 100755
index 0000000..b3092cc
--- /dev/null
+++ b/WebKitTools/DumpRenderTree/chromium/WebThemeEngineDRT.cpp
@@ -0,0 +1,674 @@
+/*
+ * Copyright (C) 2010 Google 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:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 "WebThemeEngineDRT.h"
+
+#include "WebThemeControlDRT.h"
+#include "public/WebRect.h"
+#include "third_party/skia/include/core/SkRect.h"
+
+// Although all this code is generic, we include these headers
+// to pull in the Windows #defines for the parts and states of
+// the controls.
+#include <vsstyle.h>
+#include <windows.h>
+
+#include <wtf/Assertions.h>
+
+using namespace WebKit;
+
+// We define this for clarity, although there really should be a DFCS_NORMAL in winuser.h.
+static const int dfcsNormal = 0x0000;
+
+static SkIRect webRectToSkIRect(const WebRect& webRect)
+{
+ SkIRect irect;
+ irect.set(webRect.x, webRect.y, webRect.x + webRect.width, webRect.y + webRect.height);
+ return irect;
+}
+
+static void drawControl(WebCanvas* canvas,
+ const WebRect& rect,
+ WebThemeControlDRT::Type ctype,
+ WebThemeControlDRT::State cstate)
+{
+ WebThemeControlDRT control(canvas, webRectToSkIRect(rect), ctype, cstate);
+ control.draw();
+}
+
+static void drawTextField(WebCanvas* canvas,
+ const WebRect& rect,
+ WebThemeControlDRT::Type ctype,
+ WebThemeControlDRT::State cstate,
+ bool drawEdges,
+ bool fillContentArea,
+ WebColor color)
+{
+ WebThemeControlDRT control(canvas, webRectToSkIRect(rect), ctype, cstate);
+ control.drawTextField(drawEdges, fillContentArea, color);
+}
+
+static void drawProgressBar(WebCanvas* canvas,
+ WebThemeControlDRT::Type ctype,
+ WebThemeControlDRT::State cstate,
+ const WebRect& barRect,
+ const WebRect& fillRect)
+{
+ WebThemeControlDRT control(canvas, webRectToSkIRect(barRect), ctype, cstate);
+ control.drawProgressBar(webRectToSkIRect(fillRect));
+}
+
+// WebThemeEngineDRT
+
+void WebThemeEngineDRT::paintButton(WebCanvas* canvas,
+ int part,
+ int state,
+ int classicState,
+ const WebRect& rect)
+{
+ WebThemeControlDRT::Type ctype = WebThemeControlDRT::UnknownType;
+ WebThemeControlDRT::State cstate = WebThemeControlDRT::UnknownState;
+
+ if (part == BP_CHECKBOX) {
+ switch (state) {
+ case CBS_UNCHECKEDNORMAL:
+ ASSERT(classicState == dfcsNormal);
+ ctype = WebThemeControlDRT::UncheckedBoxType;
+ cstate = WebThemeControlDRT::NormalState;
+ break;
+
+ case CBS_UNCHECKEDHOT:
+ ASSERT(classicState == (DFCS_BUTTONCHECK | DFCS_HOT));
+ ctype = WebThemeControlDRT::UncheckedBoxType;
+ cstate = WebThemeControlDRT::HotState;
+ break;
+
+ case CBS_UNCHECKEDPRESSED:
+ ASSERT(classicState == (DFCS_BUTTONCHECK | DFCS_PUSHED));
+ ctype = WebThemeControlDRT::UncheckedBoxType;
+ cstate = WebThemeControlDRT::PressedState;
+ break;
+
+ case CBS_UNCHECKEDDISABLED:
+ ASSERT(classicState == (DFCS_BUTTONCHECK | DFCS_INACTIVE));
+ ctype = WebThemeControlDRT::UncheckedBoxType;
+ cstate = WebThemeControlDRT::DisabledState;
+ break;
+
+ case CBS_CHECKEDNORMAL:
+ ASSERT(classicState == (DFCS_BUTTONCHECK | DFCS_CHECKED));
+ ctype = WebThemeControlDRT::CheckedBoxType;
+ cstate = WebThemeControlDRT::NormalState;
+ break;
+
+ case CBS_CHECKEDHOT:
+ ASSERT(classicState == (DFCS_BUTTONCHECK | DFCS_CHECKED | DFCS_HOT));
+ ctype = WebThemeControlDRT::CheckedBoxType;
+ cstate = WebThemeControlDRT::HotState;
+ break;
+
+ case CBS_CHECKEDPRESSED:
+ ASSERT(classicState == (DFCS_BUTTONCHECK | DFCS_CHECKED | DFCS_PUSHED));
+ ctype = WebThemeControlDRT::CheckedBoxType;
+ cstate = WebThemeControlDRT::PressedState;
+ break;
+
+ case CBS_CHECKEDDISABLED:
+ ASSERT(classicState == (DFCS_BUTTONCHECK | DFCS_CHECKED | DFCS_INACTIVE));
+ ctype = WebThemeControlDRT::CheckedBoxType;
+ cstate = WebThemeControlDRT::DisabledState;
+ break;
+
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ } else if (BP_RADIOBUTTON == part) {
+ switch (state) {
+ case RBS_UNCHECKEDNORMAL:
+ ASSERT(classicState == DFCS_BUTTONRADIO);
+ ctype = WebThemeControlDRT::UncheckedRadioType;
+ cstate = WebThemeControlDRT::NormalState;
+ break;
+
+ case RBS_UNCHECKEDHOT:
+ ASSERT(classicState == (DFCS_BUTTONRADIO | DFCS_HOT));
+ ctype = WebThemeControlDRT::UncheckedRadioType;
+ cstate = WebThemeControlDRT::HotState;
+ break;
+
+ case RBS_UNCHECKEDPRESSED:
+ ASSERT(classicState == (DFCS_BUTTONRADIO | DFCS_PUSHED));
+ ctype = WebThemeControlDRT::UncheckedRadioType;
+ cstate = WebThemeControlDRT::PressedState;
+ break;
+
+ case RBS_UNCHECKEDDISABLED:
+ ASSERT(classicState == (DFCS_BUTTONRADIO | DFCS_INACTIVE));
+ ctype = WebThemeControlDRT::UncheckedRadioType;
+ cstate = WebThemeControlDRT::DisabledState;
+ break;
+
+ case RBS_CHECKEDNORMAL:
+ ASSERT(classicState == (DFCS_BUTTONRADIO | DFCS_CHECKED));
+ ctype = WebThemeControlDRT::CheckedRadioType;
+ cstate = WebThemeControlDRT::NormalState;
+ break;
+
+ case RBS_CHECKEDHOT:
+ ASSERT(classicState == (DFCS_BUTTONRADIO | DFCS_CHECKED | DFCS_HOT));
+ ctype = WebThemeControlDRT::CheckedRadioType;
+ cstate = WebThemeControlDRT::HotState;
+ break;
+
+ case RBS_CHECKEDPRESSED:
+ ASSERT(classicState == (DFCS_BUTTONRADIO | DFCS_CHECKED | DFCS_PUSHED));
+ ctype = WebThemeControlDRT::CheckedRadioType;
+ cstate = WebThemeControlDRT::PressedState;
+ break;
+
+ case RBS_CHECKEDDISABLED:
+ ASSERT(classicState == (DFCS_BUTTONRADIO | DFCS_CHECKED | DFCS_INACTIVE));
+ ctype = WebThemeControlDRT::CheckedRadioType;
+ cstate = WebThemeControlDRT::DisabledState;
+ break;
+
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ } else if (BP_PUSHBUTTON == part) {
+ switch (state) {
+ case PBS_NORMAL:
+ ASSERT(classicState == DFCS_BUTTONPUSH);
+ ctype = WebThemeControlDRT::PushButtonType;
+ cstate = WebThemeControlDRT::NormalState;
+ break;
+
+ case PBS_HOT:
+ ASSERT(classicState == (DFCS_BUTTONPUSH | DFCS_HOT));
+ ctype = WebThemeControlDRT::PushButtonType;
+ cstate = WebThemeControlDRT::HotState;
+ break;
+
+ case PBS_PRESSED:
+ ASSERT(classicState == (DFCS_BUTTONPUSH | DFCS_PUSHED));
+ ctype = WebThemeControlDRT::PushButtonType;
+ cstate = WebThemeControlDRT::PressedState;
+ break;
+
+ case PBS_DISABLED:
+ ASSERT(classicState == (DFCS_BUTTONPUSH | DFCS_INACTIVE));
+ ctype = WebThemeControlDRT::PushButtonType;
+ cstate = WebThemeControlDRT::DisabledState;
+ break;
+
+ case PBS_DEFAULTED:
+ ASSERT(classicState == DFCS_BUTTONPUSH);
+ ctype = WebThemeControlDRT::PushButtonType;
+ cstate = WebThemeControlDRT::FocusedState;
+ break;
+
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ } else {
+ ASSERT_NOT_REACHED();
+ }
+
+ drawControl(canvas, rect, ctype, cstate);
+}
+
+
+void WebThemeEngineDRT::paintMenuList(WebCanvas* canvas,
+ int part,
+ int state,
+ int classicState,
+ const WebRect& rect)
+{
+ WebThemeControlDRT::Type ctype = WebThemeControlDRT::UnknownType;
+ WebThemeControlDRT::State cstate = WebThemeControlDRT::UnknownState;
+
+ if (CP_DROPDOWNBUTTON == part) {
+ ctype = WebThemeControlDRT::DropDownButtonType;
+ switch (state) {
+ case CBXS_NORMAL:
+ ASSERT(classicState == DFCS_MENUARROW);
+ cstate = WebThemeControlDRT::NormalState;
+ break;
+
+ case CBXS_HOT:
+ ASSERT(classicState == (DFCS_MENUARROW | DFCS_HOT));
+ cstate = WebThemeControlDRT::HoverState;
+ break;
+
+ case CBXS_PRESSED:
+ ASSERT(classicState == (DFCS_MENUARROW | DFCS_PUSHED));
+ cstate = WebThemeControlDRT::PressedState;
+ break;
+
+ case CBXS_DISABLED:
+ ASSERT(classicState == (DFCS_MENUARROW | DFCS_INACTIVE));
+ cstate = WebThemeControlDRT::DisabledState;
+ break;
+
+ default:
+ CRASH();
+ break;
+ }
+ } else {
+ CRASH();
+ }
+
+ drawControl(canvas, rect, ctype, cstate);
+}
+
+void WebThemeEngineDRT::paintScrollbarArrow(WebCanvas* canvas,
+ int state,
+ int classicState,
+ const WebRect& rect)
+{
+ WebThemeControlDRT::Type ctype = WebThemeControlDRT::UnknownType;
+ WebThemeControlDRT::State cstate = WebThemeControlDRT::UnknownState;
+
+ switch (state) {
+ case ABS_UPNORMAL:
+ ASSERT(classicState == DFCS_SCROLLUP);
+ ctype = WebThemeControlDRT::UpArrowType;
+ cstate = WebThemeControlDRT::NormalState;
+ break;
+
+ case ABS_DOWNNORMAL:
+ ASSERT(classicState == DFCS_SCROLLDOWN);
+ ctype = WebThemeControlDRT::DownArrowType;
+ cstate = WebThemeControlDRT::NormalState;
+ break;
+
+ case ABS_LEFTNORMAL:
+ ASSERT(classicState == DFCS_SCROLLLEFT);
+ ctype = WebThemeControlDRT::LeftArrowType;
+ cstate = WebThemeControlDRT::NormalState;
+ break;
+
+ case ABS_RIGHTNORMAL:
+ ASSERT(classicState == DFCS_SCROLLRIGHT);
+ ctype = WebThemeControlDRT::RightArrowType;
+ cstate = WebThemeControlDRT::NormalState;
+ break;
+
+ case ABS_UPHOT:
+ ASSERT(classicState == (DFCS_SCROLLUP | DFCS_HOT));
+ ctype = WebThemeControlDRT::UpArrowType;
+ cstate = WebThemeControlDRT::HotState;
+ break;
+
+ case ABS_DOWNHOT:
+ ASSERT(classicState == (DFCS_SCROLLDOWN | DFCS_HOT));
+ ctype = WebThemeControlDRT::DownArrowType;
+ cstate = WebThemeControlDRT::HotState;
+ break;
+
+ case ABS_LEFTHOT:
+ ASSERT(classicState == (DFCS_SCROLLLEFT | DFCS_HOT));
+ ctype = WebThemeControlDRT::LeftArrowType;
+ cstate = WebThemeControlDRT::HotState;
+ break;
+
+ case ABS_RIGHTHOT:
+ ASSERT(classicState == (DFCS_SCROLLRIGHT | DFCS_HOT));
+ ctype = WebThemeControlDRT::RightArrowType;
+ cstate = WebThemeControlDRT::HotState;
+ break;
+
+ case ABS_UPHOVER:
+ ASSERT(classicState == DFCS_SCROLLUP);
+ ctype = WebThemeControlDRT::UpArrowType;
+ cstate = WebThemeControlDRT::HoverState;
+ break;
+
+ case ABS_DOWNHOVER:
+ ASSERT(classicState == DFCS_SCROLLDOWN);
+ ctype = WebThemeControlDRT::DownArrowType;
+ cstate = WebThemeControlDRT::HoverState;
+ break;
+
+ case ABS_LEFTHOVER:
+ ASSERT(classicState == DFCS_SCROLLLEFT);
+ ctype = WebThemeControlDRT::LeftArrowType;
+ cstate = WebThemeControlDRT::HoverState;
+ break;
+
+ case ABS_RIGHTHOVER:
+ ASSERT(classicState == DFCS_SCROLLRIGHT);
+ ctype = WebThemeControlDRT::RightArrowType;
+ cstate = WebThemeControlDRT::HoverState;
+ break;
+
+ case ABS_UPPRESSED:
+ ASSERT(classicState == (DFCS_SCROLLUP | DFCS_PUSHED | DFCS_FLAT));
+ ctype = WebThemeControlDRT::UpArrowType;
+ cstate = WebThemeControlDRT::PressedState;
+ break;
+
+ case ABS_DOWNPRESSED:
+ ASSERT(classicState == (DFCS_SCROLLDOWN | DFCS_PUSHED | DFCS_FLAT));
+ ctype = WebThemeControlDRT::DownArrowType;
+ cstate = WebThemeControlDRT::PressedState;
+ break;
+
+ case ABS_LEFTPRESSED:
+ ASSERT(classicState == (DFCS_SCROLLLEFT | DFCS_PUSHED | DFCS_FLAT));
+ ctype = WebThemeControlDRT::LeftArrowType;
+ cstate = WebThemeControlDRT::PressedState;
+ break;
+
+ case ABS_RIGHTPRESSED:
+ ASSERT(classicState == (DFCS_SCROLLRIGHT | DFCS_PUSHED | DFCS_FLAT));
+ ctype = WebThemeControlDRT::RightArrowType;
+ cstate = WebThemeControlDRT::PressedState;
+ break;
+
+ case ABS_UPDISABLED:
+ ASSERT(classicState == (DFCS_SCROLLUP | DFCS_INACTIVE));
+ ctype = WebThemeControlDRT::UpArrowType;
+ cstate = WebThemeControlDRT::DisabledState;
+ break;
+
+ case ABS_DOWNDISABLED:
+ ASSERT(classicState == (DFCS_SCROLLDOWN | DFCS_INACTIVE));
+ ctype = WebThemeControlDRT::DownArrowType;
+ cstate = WebThemeControlDRT::DisabledState;
+ break;
+
+ case ABS_LEFTDISABLED:
+ ASSERT(classicState == (DFCS_SCROLLLEFT | DFCS_INACTIVE));
+ ctype = WebThemeControlDRT::LeftArrowType;
+ cstate = WebThemeControlDRT::DisabledState;
+ break;
+
+ case ABS_RIGHTDISABLED:
+ ASSERT(classicState == (DFCS_SCROLLRIGHT | DFCS_INACTIVE));
+ ctype = WebThemeControlDRT::RightArrowType;
+ cstate = WebThemeControlDRT::DisabledState;
+ break;
+
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+
+ drawControl(canvas, rect, ctype, cstate);
+}
+
+void WebThemeEngineDRT::paintScrollbarThumb(WebCanvas* canvas,
+ int part,
+ int state,
+ int classicState,
+ const WebRect& rect)
+{
+ WebThemeControlDRT::Type ctype = WebThemeControlDRT::UnknownType;
+ WebThemeControlDRT::State cstate = WebThemeControlDRT::UnknownState;
+
+ switch (part) {
+ case SBP_THUMBBTNHORZ:
+ ctype = WebThemeControlDRT::HorizontalScrollThumbType;
+ break;
+
+ case SBP_THUMBBTNVERT:
+ ctype = WebThemeControlDRT::VerticalScrollThumbType;
+ break;
+
+ case SBP_GRIPPERHORZ:
+ ctype = WebThemeControlDRT::HorizontalScrollGripType;
+ break;
+
+ case SBP_GRIPPERVERT:
+ ctype = WebThemeControlDRT::VerticalScrollGripType;
+ break;
+
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+
+ switch (state) {
+ case SCRBS_NORMAL:
+ ASSERT(classicState == dfcsNormal);
+ cstate = WebThemeControlDRT::NormalState;
+ break;
+
+ case SCRBS_HOT:
+ ASSERT(classicState == DFCS_HOT);
+ cstate = WebThemeControlDRT::HotState;
+ break;
+
+ case SCRBS_HOVER:
+ ASSERT(classicState == dfcsNormal);
+ cstate = WebThemeControlDRT::HoverState;
+ break;
+
+ case SCRBS_PRESSED:
+ ASSERT(classicState == dfcsNormal);
+ cstate = WebThemeControlDRT::PressedState;
+ break;
+
+ case SCRBS_DISABLED:
+ ASSERT_NOT_REACHED(); // This should never happen in practice.
+ break;
+
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+
+ drawControl(canvas, rect, ctype, cstate);
+}
+
+void WebThemeEngineDRT::paintScrollbarTrack(WebCanvas* canvas,
+ int part,
+ int state,
+ int classicState,
+ const WebRect& rect,
+ const WebRect& alignRect)
+{
+ WebThemeControlDRT::Type ctype = WebThemeControlDRT::UnknownType;
+ WebThemeControlDRT::State cstate = WebThemeControlDRT::UnknownState;
+
+ switch (part) {
+ case SBP_UPPERTRACKHORZ:
+ ctype = WebThemeControlDRT::HorizontalScrollTrackBackType;
+ break;
+
+ case SBP_LOWERTRACKHORZ:
+ ctype = WebThemeControlDRT::HorizontalScrollTrackForwardType;
+ break;
+
+ case SBP_UPPERTRACKVERT:
+ ctype = WebThemeControlDRT::VerticalScrollTrackBackType;
+ break;
+
+ case SBP_LOWERTRACKVERT:
+ ctype = WebThemeControlDRT::VerticalScrollTrackForwardType;
+ break;
+
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+
+ switch (state) {
+ case SCRBS_NORMAL:
+ ASSERT(classicState == dfcsNormal);
+ cstate = WebThemeControlDRT::NormalState;
+ break;
+
+ case SCRBS_HOT:
+ ASSERT_NOT_REACHED(); // This should never happen in practice.
+ break;
+
+ case SCRBS_HOVER:
+ ASSERT(classicState == dfcsNormal);
+ cstate = WebThemeControlDRT::HoverState;
+ break;
+
+ case SCRBS_PRESSED:
+ ASSERT_NOT_REACHED(); // This should never happen in practice.
+ break;
+
+ case SCRBS_DISABLED:
+ ASSERT(classicState == DFCS_INACTIVE);
+ cstate = WebThemeControlDRT::DisabledState;
+ break;
+
+ default:
+ CRASH();
+ break;
+ }
+
+ drawControl(canvas, rect, ctype, cstate);
+}
+
+void WebThemeEngineDRT::paintTextField(WebCanvas* canvas,
+ int part,
+ int state,
+ int classicState,
+ const WebRect& rect,
+ WebColor color,
+ bool fillContentArea,
+ bool drawEdges)
+{
+ WebThemeControlDRT::Type ctype = WebThemeControlDRT::UnknownType;
+ WebThemeControlDRT::State cstate = WebThemeControlDRT::UnknownState;
+
+ ASSERT(EP_EDITTEXT == part);
+ ctype = WebThemeControlDRT::TextFieldType;
+
+ switch (state) {
+ case ETS_NORMAL:
+ ASSERT(classicState == dfcsNormal);
+ cstate = WebThemeControlDRT::NormalState;
+ break;
+
+ case ETS_HOT:
+ ASSERT(classicState == DFCS_HOT);
+ cstate = WebThemeControlDRT::HotState;
+ break;
+
+ case ETS_DISABLED:
+ ASSERT(classicState == DFCS_INACTIVE);
+ cstate = WebThemeControlDRT::DisabledState;
+ break;
+
+ case ETS_SELECTED:
+ ASSERT(classicState == DFCS_PUSHED);
+ cstate = WebThemeControlDRT::PressedState;
+ break;
+
+ case ETS_FOCUSED:
+ ASSERT(classicState == dfcsNormal);
+ cstate = WebThemeControlDRT::FocusedState;
+ break;
+
+ case ETS_READONLY:
+ ASSERT(classicState == dfcsNormal);
+ cstate = WebThemeControlDRT::ReadOnlyState;
+ break;
+
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+
+ drawTextField(canvas, rect, ctype, cstate, drawEdges, fillContentArea, color);
+}
+
+void WebThemeEngineDRT::paintTrackbar(WebCanvas* canvas,
+ int part,
+ int state,
+ int classicState,
+ const WebRect& rect)
+{
+ WebThemeControlDRT::Type ctype = WebThemeControlDRT::UnknownType;
+ WebThemeControlDRT::State cstate = WebThemeControlDRT::UnknownState;
+
+ if (TKP_THUMBBOTTOM == part) {
+ ctype = WebThemeControlDRT::HorizontalSliderThumbType;
+ switch (state) {
+ case TUS_NORMAL:
+ ASSERT(classicState == dfcsNormal);
+ cstate = WebThemeControlDRT::NormalState;
+ break;
+
+ case TUS_HOT:
+ ASSERT(classicState == DFCS_HOT);
+ cstate = WebThemeControlDRT::HotState;
+ break;
+
+ case TUS_DISABLED:
+ ASSERT(classicState == DFCS_INACTIVE);
+ cstate = WebThemeControlDRT::DisabledState;
+ break;
+
+ case TUS_PRESSED:
+ ASSERT(classicState == DFCS_PUSHED);
+ cstate = WebThemeControlDRT::PressedState;
+ break;
+
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ } else if (TKP_TRACK == part) {
+ ctype = WebThemeControlDRT::HorizontalSliderTrackType;
+ ASSERT(part == TUS_NORMAL);
+ ASSERT(classicState == dfcsNormal);
+ cstate = WebThemeControlDRT::NormalState;
+ } else {
+ ASSERT_NOT_REACHED();
+ }
+
+ drawControl(canvas, rect, ctype, cstate);
+}
+
+
+void WebThemeEngineDRT::paintProgressBar(WebKit::WebCanvas* canvas,
+ const WebKit::WebRect& barRect,
+ const WebKit::WebRect& valueRect,
+ bool determinate,
+ double)
+{
+ WebThemeControlDRT::Type ctype = WebThemeControlDRT::ProgressBarType;
+ WebThemeControlDRT::State cstate = determinate ? WebThemeControlDRT::NormalState
+ : WebThemeControlDRT::IndeterminateState;
+ drawProgressBar(canvas, ctype, cstate, barRect, valueRect);
+}
+
diff --git a/WebKitTools/DumpRenderTree/chromium/WebThemeEngineDRT.h b/WebKitTools/DumpRenderTree/chromium/WebThemeEngineDRT.h
new file mode 100755
index 0000000..89805b1
--- /dev/null
+++ b/WebKitTools/DumpRenderTree/chromium/WebThemeEngineDRT.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2010 Google 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:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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.
+ */
+
+// This implements the WebThemeEngine API used by the Windows version of
+// Chromium to render native form controls like checkboxes, radio buttons,
+// and scroll bars.
+// The normal implementation (native_theme) renders the controls using either
+// the UXTheme theming engine present in XP, Vista, and Win 7, or the "classic"
+// theme used if that theme is selected in the Desktop settings.
+// Unfortunately, both of these themes render controls differently on the
+// different versions of Windows.
+//
+// In order to ensure maximum consistency of baselines across the different
+// Windows versions, we provide a simple implementation for DRT here
+// instead. These controls are actually platform-independent (they're rendered
+// using Skia) and could be used on Linux and the Mac as well, should we
+// choose to do so at some point.
+//
+
+#ifndef WebThemeEngineDRT_h
+#define WebThemeEngineDRT_h
+
+#include "public/WebThemeEngine.h"
+#include <wtf/Noncopyable.h>
+
+class WebThemeEngineDRT : public WebKit::WebThemeEngine, public Noncopyable {
+public:
+ WebThemeEngineDRT() {}
+
+ // WebThemeEngine methods:
+ virtual void paintButton(
+ WebKit::WebCanvas*, int part, int state, int classicState,
+ const WebKit::WebRect&);
+
+ virtual void paintMenuList(
+ WebKit::WebCanvas*, int part, int state, int classicState,
+ const WebKit::WebRect&);
+
+ virtual void paintScrollbarArrow(
+ WebKit::WebCanvas*, int state, int classicState,
+ const WebKit::WebRect&);
+
+ virtual void paintScrollbarThumb(
+ WebKit::WebCanvas*, int part, int state, int classicState,
+ const WebKit::WebRect&);
+
+ virtual void paintScrollbarTrack(
+ WebKit::WebCanvas*, int part, int state, int classicState,
+ const WebKit::WebRect&, const WebKit::WebRect& alignRect);
+
+ virtual void paintTextField(
+ WebKit::WebCanvas*, int part, int state, int classicState,
+ const WebKit::WebRect&, WebKit::WebColor, bool fillContentArea,
+ bool drawEdges);
+
+ virtual void paintTrackbar(
+ WebKit::WebCanvas*, int part, int state, int classicState,
+ const WebKit::WebRect&);
+
+ virtual void paintProgressBar(
+ WebKit::WebCanvas*, const WebKit::WebRect& barRect,
+ const WebKit::WebRect& valueRect,
+ bool determinate, double time);
+};
+
+#endif // WebThemeEngineDRT_h
diff --git a/WebKitTools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp b/WebKitTools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp
index 3735d0a..d186ffa 100644
--- a/WebKitTools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp
+++ b/WebKitTools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp
@@ -112,6 +112,12 @@ AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
return 0;
}
+AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
+{
+ // FIXME: implement
+ return 0;
+}
+
AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
{
Vector<AccessibilityUIElement> children;
diff --git a/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp
index 02c0abb..14577f1 100644
--- a/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp
+++ b/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp
@@ -388,8 +388,18 @@ void dump()
if (gLayoutTestController->dumpAsText())
result = dumpFramesAsText(mainFrame);
- else
+ else {
+ // Widget resizing is done asynchronously in GTK+. We pump the main
+ // loop here, to flush any pending resize requests. This prevents
+ // timing issues which affect the size of elements in the output.
+ // We only enable this workaround for tests that print the render tree
+ // because this seems to break some dumpAsText tests: see bug 39988
+ // After fixing that test, we should apply this approach to all dumps.
+ while (gtk_events_pending())
+ gtk_main_iteration();
+
result = webkit_web_frame_dump_render_tree(mainFrame);
+ }
if (!result) {
const char* errorMessage;
@@ -525,8 +535,10 @@ static void runTest(const string& testPathOrURL)
gtk_main();
// If developer extras enabled Web Inspector may have been open by the test.
- if (shouldEnableDeveloperExtras(pathOrURL.c_str()))
+ if (shouldEnableDeveloperExtras(pathOrURL.c_str())) {
gLayoutTestController->closeWebInspector();
+ gLayoutTestController->setDeveloperExtrasEnabled(false);
+ }
// Also check if we still have opened webViews and free them.
if (gLayoutTestController->closeRemainingWindowsWhenComplete() || webViewList) {
@@ -663,7 +675,7 @@ static void webViewWindowObjectCleared(WebKitWebView* view, WebKitWebFrame* fram
ASSERT(!exception);
JSStringRef eventSenderStr = JSStringCreateWithUTF8CString("eventSender");
- JSValueRef eventSender = makeEventSender(context);
+ JSValueRef eventSender = makeEventSender(context, !webkit_web_frame_get_parent(frame));
JSObjectSetProperty(context, windowObject, eventSenderStr, eventSender, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, 0);
JSStringRelease(eventSenderStr);
}
diff --git a/WebKitTools/DumpRenderTree/gtk/EventSender.cpp b/WebKitTools/DumpRenderTree/gtk/EventSender.cpp
index 9c27d8c..0ef4a42 100644
--- a/WebKitTools/DumpRenderTree/gtk/EventSender.cpp
+++ b/WebKitTools/DumpRenderTree/gtk/EventSender.cpp
@@ -45,28 +45,27 @@
#include <gdk/gdkkeysyms.h>
#include <string.h>
-// TODO: Currently drag and drop related code is left out and
-// should be merged once we have drag and drop support in WebCore.
+// FIXME: Implement support for synthesizing drop events.
extern "C" {
extern void webkit_web_frame_layout(WebKitWebFrame* frame);
}
-static bool down = false;
-static bool currentEventButton = 1;
-static bool dragMode = true;
-static bool replayingSavedEvents = false;
+static bool dragMode;
+static int timeOffset = 0;
+
static int lastMousePositionX;
static int lastMousePositionY;
-
static int lastClickPositionX;
static int lastClickPositionY;
-static int clickCount = 0;
+static int lastClickTimeOffset;
+static int lastClickButton;
+static int buttonCurrentlyDown;
+static int clickCount;
struct DelayedMessage {
GdkEvent event;
gulong delay;
- gboolean isDragEvent;
};
static DelayedMessage msgQueue[1024];
@@ -84,6 +83,10 @@ enum KeyLocationCode {
DOM_KEY_LOCATION_NUMPAD = 0x03
};
+static void sendOrQueueEvent(GdkEvent, bool = true);
+static void dispatchEvent(GdkEvent event);
+static guint getStateFlags();
+
static JSValueRef getDragModeCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
{
return JSValueMakeBoolean(context, dragMode);
@@ -97,46 +100,15 @@ static bool setDragModeCallback(JSContextRef context, JSObjectRef object, JSStri
static JSValueRef leapForwardCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
- // FIXME: Add proper support for forward leaps
- return JSValueMakeUndefined(context);
-}
-
-static JSValueRef contextClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- webkit_web_frame_layout(mainFrame);
-
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- if (!view)
- return JSValueMakeUndefined(context);
-
- GdkEvent event;
- memset(&event, 0, sizeof(event));
- event.button.button = 3;
- event.button.x = lastMousePositionX;
- event.button.y = lastMousePositionY;
- event.button.window = GTK_WIDGET(view)->window;
-
- gboolean return_val;
- down = true;
- event.type = GDK_BUTTON_PRESS;
- g_signal_emit_by_name(view, "button_press_event", &event, &return_val);
-
- down = false;
- event.type = GDK_BUTTON_RELEASE;
- g_signal_emit_by_name(view, "button_release_event", &event, &return_val);
+ if (argumentCount > 0) {
+ msgQueue[endOfQueue].delay = JSValueToNumber(context, arguments[0], exception);
+ timeOffset += msgQueue[endOfQueue].delay;
+ ASSERT(!exception || !*exception);
+ }
return JSValueMakeUndefined(context);
}
-static void updateClickCount(int button)
-{
- // FIXME: take the last clicked button number and the time of last click into account.
- if (lastClickPositionX != lastMousePositionX || lastClickPositionY != lastMousePositionY || currentEventButton != button)
- clickCount = 1;
- else
- clickCount++;
-}
-
#if !GTK_CHECK_VERSION(2,17,3)
static void getRootCoords(GtkWidget* view, int* rootX, int* rootY)
{
@@ -152,131 +124,139 @@ static void getRootCoords(GtkWidget* view, int* rootX, int* rootY)
}
#endif
-static JSValueRef mouseDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+bool prepareMouseButtonEvent(GdkEvent* event, int eventSenderButtonNumber)
{
WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
if (!view)
- return JSValueMakeUndefined(context);
+ return false;
+
+ // The logic for mapping EventSender button numbers to GDK button
+ // numbers originates from the Windows EventSender.
+ int gdkButtonNumber = 3;
+ if (eventSenderButtonNumber >= 0 && eventSenderButtonNumber <= 2)
+ gdkButtonNumber = eventSenderButtonNumber + 1;
+
+ // fast/events/mouse-click-events expects the 4th button
+ // to be event.button = 1, so send a middle-button event.
+ else if (eventSenderButtonNumber == 3)
+ gdkButtonNumber = 2;
+
+ memset(event, 0, sizeof(event));
+ event->button.button = gdkButtonNumber;
+ event->button.x = lastMousePositionX;
+ event->button.y = lastMousePositionY;
+ event->button.window = GTK_WIDGET(view)->window;
+ event->button.device = gdk_device_get_core_pointer();
+ event->button.state = getStateFlags();
+
+ // Mouse up & down events dispatched via g_signal_emit_by_name must offset
+ // their time value, so that WebKit can detect where sequences of mouse
+ // clicks begin and end. This should not interfere with GDK or GTK+ event
+ // processing, because the event is only seen by the widget.
+ event->button.time = GDK_CURRENT_TIME + timeOffset;
+
+ int xRoot, yRoot;
+#if GTK_CHECK_VERSION(2, 17, 3)
+ gdk_window_get_root_coords(GTK_WIDGET(view)->window, lastMousePositionX, lastMousePositionY, &xRoot, &yRoot);
+#else
+ getRootCoords(GTK_WIDGET(view), &xRoot, &yRoot);
+#endif
+ event->button.x_root = xRoot;
+ event->button.y_root = yRoot;
- down = true;
+ return true;
+}
+static JSValueRef contextClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
GdkEvent event;
- memset(&event, 0, sizeof(event));
+ if (!prepareMouseButtonEvent(&event, 2))
+ return JSValueMakeUndefined(context);
+
event.type = GDK_BUTTON_PRESS;
- event.button.button = 1;
+ sendOrQueueEvent(event);
+ event.type = GDK_BUTTON_RELEASE;
+ sendOrQueueEvent(event);
+
+ return JSValueMakeUndefined(context);
+}
+
+static void updateClickCount(int button)
+{
+ if (lastClickPositionX != lastMousePositionX
+ || lastClickPositionY != lastMousePositionY
+ || lastClickButton != button
+ || timeOffset - lastClickTimeOffset >= 1)
+ clickCount = 1;
+ else
+ clickCount++;
+}
+static JSValueRef mouseDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ int button = 0;
if (argumentCount == 1) {
- event.button.button = (int)JSValueToNumber(context, arguments[0], exception) + 1;
+ button = static_cast<int>(JSValueToNumber(context, arguments[0], exception));
g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
}
- currentEventButton = event.button.button;
-
- event.button.x = lastMousePositionX;
- event.button.y = lastMousePositionY;
- event.button.window = GTK_WIDGET(view)->window;
- event.button.time = GDK_CURRENT_TIME;
- event.button.device = gdk_device_get_core_pointer();
-
- int x_root, y_root;
-#if GTK_CHECK_VERSION(2,17,3)
- gdk_window_get_root_coords(GTK_WIDGET(view)->window, lastMousePositionX, lastMousePositionY, &x_root, &y_root);
-#else
- getRootCoords(GTK_WIDGET(view), &x_root, &y_root);
-#endif
+ GdkEvent event;
+ if (!prepareMouseButtonEvent(&event, button))
+ return JSValueMakeUndefined(context);
- event.button.x_root = x_root;
- event.button.y_root = y_root;
+ buttonCurrentlyDown = event.button.button;
+ // Normally GDK will send both GDK_BUTTON_PRESS and GDK_2BUTTON_PRESS for
+ // the second button press during double-clicks. WebKit GTK+ selectively
+ // ignores the first GDK_BUTTON_PRESS of that pair using gdk_event_peek.
+ // Since our events aren't ever going onto the GDK event queue, WebKit won't
+ // be able to filter out the first GDK_BUTTON_PRESS, so we just don't send
+ // it here. Eventually this code should probably figure out a way to get all
+ // appropriate events onto the event queue and this work-around should be
+ // removed.
updateClickCount(event.button.button);
+ if (clickCount == 2)
+ event.type = GDK_2BUTTON_PRESS;
+ else if (clickCount == 3)
+ event.type = GDK_3BUTTON_PRESS;
+ else
+ event.type = GDK_BUTTON_PRESS;
- if (!msgQueue[endOfQueue].delay) {
- webkit_web_frame_layout(mainFrame);
-
- gboolean return_val;
- g_signal_emit_by_name(view, "button_press_event", &event, &return_val);
- if (clickCount == 2) {
- event.type = GDK_2BUTTON_PRESS;
- g_signal_emit_by_name(view, "button_press_event", &event, &return_val);
- }
- } else {
- // replaySavedEvents should have the required logic to make leapForward delays work
- msgQueue[endOfQueue++].event = event;
- replaySavedEvents();
- }
-
+ sendOrQueueEvent(event);
return JSValueMakeUndefined(context);
}
static guint getStateFlags()
{
- guint state = 0;
-
- if (down) {
- if (currentEventButton == 1)
- state = GDK_BUTTON1_MASK;
- else if (currentEventButton == 2)
- state = GDK_BUTTON2_MASK;
- else if (currentEventButton == 3)
- state = GDK_BUTTON3_MASK;
- } else
- state = 0;
-
- return state;
+ if (buttonCurrentlyDown == 1)
+ return GDK_BUTTON1_MASK;
+ if (buttonCurrentlyDown == 2)
+ return GDK_BUTTON2_MASK;
+ if (buttonCurrentlyDown == 3)
+ return GDK_BUTTON3_MASK;
+ return 0;
}
static JSValueRef mouseUpCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
-
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- if (!view)
- return JSValueMakeUndefined(context);
-
- GdkEvent event;
- memset(&event, 0, sizeof(event));
- event.type = GDK_BUTTON_RELEASE;
- event.button.button = 1;
-
+ int button = 0;
if (argumentCount == 1) {
- event.button.button = (int)JSValueToNumber(context, arguments[0], exception) + 1;
+ button = static_cast<int>(JSValueToNumber(context, arguments[0], exception));
g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
}
- currentEventButton = event.button.button;
-
- event.button.x = lastMousePositionX;
- event.button.y = lastMousePositionY;
- event.button.window = GTK_WIDGET(view)->window;
- event.button.time = GDK_CURRENT_TIME;
- event.button.device = gdk_device_get_core_pointer();
- event.button.state = getStateFlags();
-
- down = false;
-
- int x_root, y_root;
-#if GTK_CHECK_VERSION(2,17,3)
- gdk_window_get_root_coords(GTK_WIDGET(view)->window, lastMousePositionX, lastMousePositionY, &x_root, &y_root);
-#else
- getRootCoords(GTK_WIDGET(view), &x_root, &y_root);
-#endif
-
- event.button.x_root = x_root;
- event.button.y_root = y_root;
-
- if ((dragMode && !replayingSavedEvents) || msgQueue[endOfQueue].delay) {
- msgQueue[endOfQueue].event = event;
- msgQueue[endOfQueue++].isDragEvent = true;
- replaySavedEvents();
- } else {
- webkit_web_frame_layout(mainFrame);
-
- gboolean return_val;
- g_signal_emit_by_name(view, "button_release_event", &event, &return_val);
- }
+ GdkEvent event;
+ if (!prepareMouseButtonEvent(&event, button))
+ return JSValueMakeUndefined(context);
lastClickPositionX = lastMousePositionX;
lastClickPositionY = lastMousePositionY;
+ lastClickButton = buttonCurrentlyDown;
+ lastClickTimeOffset = timeOffset;
+ buttonCurrentlyDown = 0;
+ event.type = GDK_BUTTON_RELEASE;
+ sendOrQueueEvent(event);
return JSValueMakeUndefined(context);
}
@@ -299,32 +279,22 @@ static JSValueRef mouseMoveToCallback(JSContextRef context, JSObjectRef function
event.type = GDK_MOTION_NOTIFY;
event.motion.x = lastMousePositionX;
event.motion.y = lastMousePositionY;
+
event.motion.time = GDK_CURRENT_TIME;
event.motion.window = GTK_WIDGET(view)->window;
event.motion.device = gdk_device_get_core_pointer();
+ event.motion.state = getStateFlags();
- int x_root, y_root;
+ int xRoot, yRoot;
#if GTK_CHECK_VERSION(2,17,3)
- gdk_window_get_root_coords(GTK_WIDGET(view)->window, lastMousePositionX, lastMousePositionY, &x_root, &y_root);
+ gdk_window_get_root_coords(GTK_WIDGET(view)->window, lastMousePositionX, lastMousePositionY, &xRoot, &yRoot);
#else
- getRootCoords(GTK_WIDGET(view), &x_root, &y_root);
+ getRootCoords(GTK_WIDGET(view), &xRoot, &yRoot);
#endif
+ event.motion.x_root = xRoot;
+ event.motion.y_root = yRoot;
- event.motion.x_root = x_root;
- event.motion.y_root = y_root;
-
- event.motion.state = getStateFlags();
-
- if (dragMode && down && !replayingSavedEvents) {
- msgQueue[endOfQueue].event = event;
- msgQueue[endOfQueue++].isDragEvent = true;
- } else {
- webkit_web_frame_layout(mainFrame);
-
- gboolean return_val;
- g_signal_emit_by_name(view, "motion_notify_event", &event, &return_val);
- }
-
+ sendOrQueueEvent(event, false);
return JSValueMakeUndefined(context);
}
@@ -363,14 +333,7 @@ static JSValueRef mouseWheelToCallback(JSContextRef context, JSObjectRef functio
else
g_assert_not_reached();
- if (dragMode && down && !replayingSavedEvents) {
- msgQueue[endOfQueue].event = event;
- msgQueue[endOfQueue++].isDragEvent = true;
- } else {
- webkit_web_frame_layout(mainFrame);
- gtk_main_do_event(&event);
- }
-
+ sendOrQueueEvent(event);
return JSValueMakeUndefined(context);
}
@@ -383,49 +346,49 @@ static JSValueRef beginDragWithFilesCallback(JSContextRef context, JSObjectRef f
return JSValueMakeUndefined(context);
}
-void replaySavedEvents()
+static void sendOrQueueEvent(GdkEvent event, bool shouldReplaySavedEvents)
{
- // FIXME: This doesn't deal with forward leaps, but it should.
+ // Mouse move events are queued if the previous event was queued or if a
+ // delay was set up by leapForward().
+ if (buttonCurrentlyDown || endOfQueue != startOfQueue || msgQueue[endOfQueue].delay) {
+ msgQueue[endOfQueue++].event = event;
+
+ if (shouldReplaySavedEvents)
+ replaySavedEvents();
+
+ return;
+ }
+
+ dispatchEvent(event);
+}
+static void dispatchEvent(GdkEvent event)
+{
+ webkit_web_frame_layout(mainFrame);
WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
if (!view)
return;
- replayingSavedEvents = true;
-
- for (unsigned queuePos = 0; queuePos < endOfQueue; queuePos++) {
- GdkEvent event = msgQueue[queuePos].event;
- gboolean return_val;
-
- switch (event.type) {
- case GDK_BUTTON_RELEASE:
- g_signal_emit_by_name(view, "button_release_event", &event, &return_val);
- break;
- case GDK_BUTTON_PRESS:
- g_signal_emit_by_name(view, "button_press_event", &event, &return_val);
- break;
- case GDK_MOTION_NOTIFY:
- g_signal_emit_by_name(view, "motion_notify_event", &event, &return_val);
- break;
- default:
- continue;
- }
+ gtk_main_do_event(&event);
+}
- startOfQueue++;
- }
+void replaySavedEvents()
+{
+ // FIXME: Eventually we may need to have more sophisticated logic to
+ // track drag-and-drop operations.
+
+ // First send all the events that are ready to be sent
+ while (startOfQueue < endOfQueue) {
+ if (msgQueue[startOfQueue].delay) {
+ g_usleep(msgQueue[startOfQueue].delay * 1000);
+ msgQueue[startOfQueue].delay = 0;
+ }
- int numQueuedMessages = endOfQueue - startOfQueue;
- if (!numQueuedMessages) {
- startOfQueue = 0;
- endOfQueue = 0;
- replayingSavedEvents = false;
- return;
+ dispatchEvent(msgQueue[startOfQueue++].event);
}
startOfQueue = 0;
endOfQueue = 0;
-
- replayingSavedEvents = false;
}
static JSValueRef keyDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
@@ -566,13 +529,11 @@ static JSValueRef keyDownCallback(JSContextRef context, JSObjectRef function, JS
g_free(keys);
}
- gboolean return_val;
event.key.type = GDK_KEY_PRESS;
-
- g_signal_emit_by_name(view, "key-press-event", &event.key, &return_val);
+ dispatchEvent(event);
event.key.type = GDK_KEY_RELEASE;
- g_signal_emit_by_name(view, "key-release-event", &event.key, &return_val);
+ dispatchEvent(event);
return JSValueMakeUndefined(context);
}
@@ -661,17 +622,24 @@ static JSClassRef getClass(JSContextRef context)
return eventSenderClass;
}
-JSObjectRef makeEventSender(JSContextRef context)
+JSObjectRef makeEventSender(JSContextRef context, bool isTopFrame)
{
- down = false;
- dragMode = true;
- lastMousePositionX = lastMousePositionY = 0;
- lastClickPositionX = lastClickPositionY = 0;
-
- if (!replayingSavedEvents) {
- // This function can be called in the middle of a test, even
- // while replaying saved events. Resetting these while doing that
- // can break things.
+ if (isTopFrame) {
+ dragMode = true;
+
+ // Fly forward in time one second when the main frame loads. This will
+ // ensure that when a test begins clicking in the same location as
+ // a previous test, those clicks won't be interpreted as continuations
+ // of the previous test's click sequences.
+ timeOffset += 1000;
+
+ lastMousePositionX = lastMousePositionY = 0;
+ lastClickPositionX = lastClickPositionY = 0;
+ lastClickTimeOffset = 0;
+ lastClickButton = 0;
+ buttonCurrentlyDown = 0;
+ clickCount = 0;
+
endOfQueue = 0;
startOfQueue = 0;
}
diff --git a/WebKitTools/DumpRenderTree/gtk/EventSender.h b/WebKitTools/DumpRenderTree/gtk/EventSender.h
index 272e8a9..ce33ccc 100644
--- a/WebKitTools/DumpRenderTree/gtk/EventSender.h
+++ b/WebKitTools/DumpRenderTree/gtk/EventSender.h
@@ -33,7 +33,7 @@
typedef const struct OpaqueJSContext* JSContextRef;
typedef struct OpaqueJSValue* JSObjectRef;
-JSObjectRef makeEventSender(JSContextRef context);
+JSObjectRef makeEventSender(JSContextRef context, bool isTopFrame);
void replaySavedEvents();
#endif
diff --git a/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm b/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm
index 3fa9c40..939398d 100644
--- a/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm
+++ b/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm
@@ -337,6 +337,17 @@ AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
return 0;
}
+AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
+{
+ BEGIN_AX_OBJC_EXCEPTIONS
+ NSArray* objects = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
+ if (index < [objects count])
+ return [objects objectAtIndex:index];
+ END_AX_OBJC_EXCEPTIONS
+
+ return 0;
+}
+
AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
{
BEGIN_AX_OBJC_EXCEPTIONS
diff --git a/WebKitTools/DumpRenderTree/mac/Configurations/Base.xcconfig b/WebKitTools/DumpRenderTree/mac/Configurations/Base.xcconfig
index 5f989e0..28a0518 100644
--- a/WebKitTools/DumpRenderTree/mac/Configurations/Base.xcconfig
+++ b/WebKitTools/DumpRenderTree/mac/Configurations/Base.xcconfig
@@ -27,6 +27,7 @@ GCC_PREPROCESSOR_DEFINITIONS = ENABLE_DASHBOARD_SUPPORT WEBKIT_VERSION_MIN_REQUI
DEBUG_INFORMATION_FORMAT = dwarf
PREBINDING = NO
GCC_C_LANGUAGE_STANDARD = gnu99
+GCC_OBJC_CALL_CXX_CDTORS = YES
GCC_PRECOMPILE_PREFIX_HEADER = YES
GCC_TREAT_WARNINGS_AS_ERRORS = YES
GCC_WARN_UNUSED_FUNCTION = YES
diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm b/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm
index 8fd5298..9e4b203 100644
--- a/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm
+++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm
@@ -41,6 +41,7 @@
#import "HistoryDelegate.h"
#import "JavaScriptThreading.h"
#import "LayoutTestController.h"
+#import "MockGeolocationProvider.h"
#import "NavigationController.h"
#import "ObjCPlugin.h"
#import "ObjCPluginFunction.h"
@@ -291,6 +292,7 @@ WebView *createWebViewAndOffscreenWindow()
[webView setFrameLoadDelegate:frameLoadDelegate];
[webView setEditingDelegate:editingDelegate];
[webView setResourceLoadDelegate:resourceLoadDelegate];
+ [webView _setGeolocationProvider:[MockGeolocationProvider shared]];
// Register the same schemes that Safari does
[WebView registerURLSchemeAsLocal:@"feed"];
@@ -1181,6 +1183,8 @@ static void resetWebViewToConsistentStateBeforeTesting()
[WebView _setUsesTestModeFocusRingColor:YES];
[WebView _resetOriginAccessWhitelists];
+
+ [[MockGeolocationProvider shared] stopTimer];
}
static void runTest(const string& testPathOrURL)
@@ -1291,8 +1295,10 @@ static void runTest(const string& testPathOrURL)
}
// If developer extras enabled Web Inspector may have been open by the test.
- if (shouldEnableDeveloperExtras(pathOrURL.c_str()))
+ if (shouldEnableDeveloperExtras(pathOrURL.c_str())) {
gLayoutTestController->closeWebInspector();
+ gLayoutTestController->setDeveloperExtrasEnabled(false);
+ }
resetWebViewToConsistentStateBeforeTesting();
diff --git a/WebKitTools/DumpRenderTree/mac/EventSendingController.mm b/WebKitTools/DumpRenderTree/mac/EventSendingController.mm
index b5b6f82..73831ff 100644
--- a/WebKitTools/DumpRenderTree/mac/EventSendingController.mm
+++ b/WebKitTools/DumpRenderTree/mac/EventSendingController.mm
@@ -122,7 +122,7 @@ BOOL replayingSavedEvents;
{
if (aSelector == @selector(beginDragWithFiles:)
|| aSelector == @selector(clearKillRing)
- || aSelector == @selector(contextClick:)
+ || aSelector == @selector(contextClick)
|| aSelector == @selector(enableDOMUIEventLogging:)
|| aSelector == @selector(fireKeyboardEventsToElement:)
|| aSelector == @selector(keyDown:withModifiers:withLocation:)
@@ -152,7 +152,7 @@ BOOL replayingSavedEvents;
{
if (aSelector == @selector(beginDragWithFiles:))
return @"beginDragWithFiles";
- if (aSelector == @selector(contextClick:))
+ if (aSelector == @selector(contextClick))
return @"contextClick";
if (aSelector == @selector(enableDOMUIEventLogging:))
return @"enableDOMUIEventLogging";
@@ -494,7 +494,7 @@ static int buildModifierFlags(const WebScriptObject* modifiers)
[self mouseScrollByX:x andY:y continuously:NO];
}
-- (void)contextClick:(BOOL)shouldPrintMenuItems
+- (NSArray *)contextClick
{
[[[mainFrame frameView] documentView] layout];
[self updateClickCountForButton:RightMouseButton];
@@ -510,21 +510,24 @@ static int buildModifierFlags(const WebScriptObject* modifiers)
pressure:0.0];
NSView *subView = [[mainFrame webView] hitTest:[event locationInWindow]];
+ NSMutableArray *menuItemStrings = [NSMutableArray array];
+
if (subView) {
NSMenu* menu = [subView menuForEvent:event];
- if (shouldPrintMenuItems) {
- printf("ContextMenuItems: ");
- for (int i = 0; i < [menu numberOfItems]; ++i) {
- NSMenuItem* menuItem = [menu itemAtIndex:i];
- if (!strcmp("Inspect Element", [[menuItem title] UTF8String]))
- continue;
- if (i > 0)
- printf(", ");
- fputs([menuItem isSeparatorItem] ? "<separator>" : [[menuItem title] UTF8String], stdout);
- }
- printf("\n");
+
+ for (int i = 0; i < [menu numberOfItems]; ++i) {
+ NSMenuItem* menuItem = [menu itemAtIndex:i];
+ if (!strcmp("Inspect Element", [[menuItem title] UTF8String]))
+ continue;
+
+ if ([menuItem isSeparatorItem])
+ [menuItemStrings addObject:@"<separator>"];
+ else
+ [menuItemStrings addObject:[menuItem title]];
}
}
+
+ return menuItemStrings;
}
- (void)scheduleAsynchronousClick
diff --git a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm
index 898235b..eb01090 100644
--- a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm
+++ b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm
@@ -31,6 +31,7 @@
#import "LayoutTestController.h"
#import "EditingDelegate.h"
+#import "MockGeolocationProvider.h"
#import "PolicyDelegate.h"
#import "WorkQueue.h"
#import "WorkQueueItem.h"
@@ -47,7 +48,7 @@
#import <WebKit/WebDatabaseManagerPrivate.h>
#import <WebKit/WebFrame.h>
#import <WebKit/WebFrameViewPrivate.h>
-#import <WebKit/WebGeolocationMockPrivate.h>
+#import <WebKit/WebGeolocationPosition.h>
#import <WebKit/WebHTMLRepresentation.h>
#import <WebKit/WebHTMLViewPrivate.h>
#import <WebKit/WebHistory.h>
@@ -55,6 +56,7 @@
#import <WebKit/WebIconDatabasePrivate.h>
#import <WebKit/WebInspectorPrivate.h>
#import <WebKit/WebNSURLExtras.h>
+#import <WebKit/WebKitErrors.h>
#import <WebKit/WebPreferences.h>
#import <WebKit/WebPreferencesPrivate.h>
#import <WebKit/WebScriptWorld.h>
@@ -298,14 +300,17 @@ void LayoutTestController::setDomainRelaxationForbiddenForURLScheme(bool forbidd
void LayoutTestController::setMockGeolocationPosition(double latitude, double longitude, double accuracy)
{
- [WebGeolocationMock setPosition:latitude:longitude:accuracy];
+ WebGeolocationPosition *position = [[WebGeolocationPosition alloc] initWithTimestamp:0 latitude:latitude longitude:longitude accuracy:accuracy];
+ [[MockGeolocationProvider shared] setPosition:position];
+ [position release];
}
void LayoutTestController::setMockGeolocationError(int code, JSStringRef message)
{
RetainPtr<CFStringRef> messageCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, message));
NSString *messageNS = (NSString *)messageCF.get();
- [WebGeolocationMock setError:code:messageNS];
+ NSError *error = [NSError errorWithDomain:WebKitErrorDomain code:code userInfo:[NSDictionary dictionaryWithObject:messageNS forKey:NSLocalizedDescriptionKey]];
+ [[MockGeolocationProvider shared] setError:error];
}
void LayoutTestController::setIconDatabaseEnabled(bool iconDatabaseEnabled)
diff --git a/WebKitTools/DumpRenderTree/mac/MockGeolocationProvider.h b/WebKitTools/DumpRenderTree/mac/MockGeolocationProvider.h
new file mode 100644
index 0000000..311d1e9
--- /dev/null
+++ b/WebKitTools/DumpRenderTree/mac/MockGeolocationProvider.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2010 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 MockGeolocationProvider_h
+#define MockGeolocationProvider_h
+
+#import <WebKit/WebViewPrivate.h>
+#import <wtf/HashSet.h>
+
+@interface MockGeolocationProvider : NSObject<WebGeolocationProvider> {
+ WebGeolocationPosition *_lastPosition;
+ NSError *_error;
+ NSTimer *_timer;
+ HashSet<WebView *> _registeredViews;
+}
+
++ (MockGeolocationProvider *)shared;
+
+- (void)setPosition:(WebGeolocationPosition *)position;
+- (void)setError:(NSError *)error;
+
+- (void)stopTimer;
+
+@end
+#endif
diff --git a/WebKitTools/DumpRenderTree/mac/MockGeolocationProvider.mm b/WebKitTools/DumpRenderTree/mac/MockGeolocationProvider.mm
new file mode 100644
index 0000000..55d7257
--- /dev/null
+++ b/WebKitTools/DumpRenderTree/mac/MockGeolocationProvider.mm
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#import "MockGeolocationProvider.h"
+
+
+@implementation MockGeolocationProvider
+
++ (MockGeolocationProvider *)shared
+{
+ static MockGeolocationProvider *provider = [[MockGeolocationProvider alloc] init];
+ return provider;
+}
+
+- (void)dealloc
+{
+ ASSERT(_registeredViews.isEmpty());
+
+ [_lastPosition release];
+ [_error release];
+ [super dealloc];
+}
+
+- (void)setPosition:(WebGeolocationPosition *)position
+{
+ if (_lastPosition != position) {
+ [_lastPosition release];
+ _lastPosition = [position retain];
+ }
+
+ [_error release];
+ _error = 0;
+
+ if (!_timer)
+ _timer = [NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(timerFired) userInfo:0 repeats:NO];
+}
+
+- (void)setError:(NSError *)error
+{
+ if (_error != error) {
+ [_error release];
+ _error = [error retain];
+ }
+
+ [_lastPosition release];
+ _lastPosition = 0;
+
+ if (!_timer)
+ _timer = [NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(timerFired) userInfo:0 repeats:NO];
+}
+
+- (void)registerWebView:(WebView *)webView
+{
+ _registeredViews.add(webView);
+}
+
+- (void)unregisterWebView:(WebView *)webView
+{
+ _registeredViews.remove(webView);
+}
+
+- (WebGeolocationPosition *)lastPosition
+{
+ return _lastPosition;
+}
+
+- (void)stopTimer
+{
+ [_timer invalidate];
+ _timer = 0;
+}
+
+- (void)timerFired
+{
+ _timer = 0;
+
+ // Expect that views won't be (un)registered while iterating.
+ HashSet<WebView*> views = _registeredViews;
+ for (HashSet<WebView*>::iterator iter = views.begin(); iter != views.end(); ++iter) {
+ if (_error)
+ [*iter _geolocationDidFailWithError:_error];
+ else
+ [*iter _geolocationDidChangePosition:_lastPosition];
+ }
+}
+
+@end
diff --git a/WebKitTools/DumpRenderTree/mac/UIDelegate.mm b/WebKitTools/DumpRenderTree/mac/UIDelegate.mm
index 19ceb95..e6754c1 100644
--- a/WebKitTools/DumpRenderTree/mac/UIDelegate.mm
+++ b/WebKitTools/DumpRenderTree/mac/UIDelegate.mm
@@ -157,12 +157,11 @@ DumpRenderTreeDraggingInfo *draggingInfo = nil;
- (void)webView:(WebView *)webView decidePolicyForGeolocationRequestFromOrigin:(WebSecurityOrigin *)origin frame:(WebFrame *)frame listener:(id<WebGeolocationPolicyListener>)listener
{
- if (gLayoutTestController->isGeolocationPermissionSet()) {
- if (gLayoutTestController->geolocationPermission())
- [listener allow];
- else
- [listener deny];
- }
+ // FIXME: If mock permission isn't set yet, we should send the response asynchronously.
+ if (gLayoutTestController->isGeolocationPermissionSet() && gLayoutTestController->geolocationPermission())
+ [listener allow];
+ else
+ [listener deny];
}
- (BOOL)webView:(WebView *)sender shouldHaltPlugin:(DOMNode *)pluginNode
diff --git a/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp
index ba9780b..f5fbb5c 100644
--- a/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp
+++ b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp
@@ -135,9 +135,9 @@ void checkPermissionCallback(QObject* receiver, const QUrl& url, NotificationPer
qobject_cast<DumpRenderTree*>(receiver)->checkPermission(url, permission);
}
-void requestPermissionCallback(QObject* receiver, QWebPage* page, const QString& origin)
+void requestPermissionCallback(QObject* receiver, const QString& origin)
{
- qobject_cast<DumpRenderTree*>(receiver)->requestPermission(page, origin);
+ qobject_cast<DumpRenderTree*>(receiver)->requestPermission(origin);
}
WebPage::WebPage(QObject* parent, DumpRenderTree* drt)
@@ -153,14 +153,13 @@ WebPage::WebPage(QObject* parent, DumpRenderTree* drt)
globalSettings->setFontSize(QWebSettings::DefaultFixedFontSize, 13);
globalSettings->setAttribute(QWebSettings::JavascriptCanOpenWindows, true);
- globalSettings->setAttribute(QWebSettings::DOMPasteAllowed, true);
+ globalSettings->setAttribute(QWebSettings::JavascriptCanAccessClipboard, true);
globalSettings->setAttribute(QWebSettings::LinksIncludedInFocusChain, false);
globalSettings->setAttribute(QWebSettings::PluginsEnabled, true);
globalSettings->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, true);
globalSettings->setAttribute(QWebSettings::JavascriptEnabled, true);
globalSettings->setAttribute(QWebSettings::PrivateBrowsingEnabled, false);
globalSettings->setAttribute(QWebSettings::SpatialNavigationEnabled, false);
- globalSettings->setAttribute(QWebSettings::JavaScriptCanAccessClipboard, true);
connect(this, SIGNAL(geometryChangeRequested(const QRect &)),
this, SLOT(setViewGeometry(const QRect & )));
@@ -168,7 +167,7 @@ WebPage::WebPage(QObject* parent, DumpRenderTree* drt)
setNetworkAccessManager(m_drt->networkAccessManager());
setPluginFactory(new TestPlugin(this));
- DumpRenderTreeSupportQt::setNotificationsReceiver(this, m_drt);
+ DumpRenderTreeSupportQt::setNotificationsReceiver(m_drt);
DumpRenderTreeSupportQt::setCheckPermissionFunction(checkPermissionCallback);
DumpRenderTreeSupportQt::setRequestPermissionFunction(requestPermissionCallback);
@@ -201,7 +200,7 @@ void WebPage::resetSettings()
settings()->resetAttribute(QWebSettings::OfflineWebApplicationCacheEnabled);
settings()->resetAttribute(QWebSettings::LocalContentCanAccessRemoteUrls);
settings()->resetAttribute(QWebSettings::PluginsEnabled);
- settings()->resetAttribute(QWebSettings::JavaScriptCanAccessClipboard);
+ settings()->resetAttribute(QWebSettings::JavascriptCanAccessClipboard);
settings()->resetAttribute(QWebSettings::AutoLoadImages);
m_drt->layoutTestController()->setCaretBrowsingEnabled(false);
@@ -349,24 +348,51 @@ QObject* WebPage::createPlugin(const QString& classId, const QUrl& url, const QS
#endif
}
+bool WebPage::allowGeolocationRequest(QWebFrame *)
+{
+ return m_drt->layoutTestController()->geolocationPermission();
+}
+
+WebViewGraphicsBased::WebViewGraphicsBased(QWidget* parent)
+ : m_item(new QGraphicsWebView)
+{
+ setScene(new QGraphicsScene(this));
+ scene()->addItem(m_item);
+}
+
DumpRenderTree::DumpRenderTree()
: m_dumpPixels(false)
, m_stdin(0)
, m_enableTextOutput(false)
, m_singleFileMode(false)
+ , m_graphicsBased(false)
, m_persistentStoragePath(QString(getenv("DUMPRENDERTREE_TEMP")))
{
+
+ QByteArray viewMode = getenv("QT_DRT_WEBVIEW_MODE");
+ if (viewMode == "graphics")
+ setGraphicsBased(true);
+
DumpRenderTreeSupportQt::overwritePluginDirectories();
QWebSettings::enablePersistentStorage(m_persistentStoragePath);
m_networkAccessManager = new NetworkAccessManager(this);
// create our primary testing page/view.
- m_mainView = new QWebView(0);
- m_mainView->resize(QSize(LayoutTestController::maxViewWidth, LayoutTestController::maxViewHeight));
- m_page = new WebPage(m_mainView, this);
- m_mainView->setPage(m_page);
+ if (isGraphicsBased()) {
+ WebViewGraphicsBased* view = new WebViewGraphicsBased(0);
+ m_page = new WebPage(view, this);
+ view->setPage(m_page);
+ m_mainView = view;
+ } else {
+ QWebView* view = new QWebView(0);
+ m_page = new WebPage(view, this);
+ view->setPage(m_page);
+ m_mainView = view;
+ }
+
m_mainView->setContextMenuPolicy(Qt::NoContextMenu);
+ m_mainView->resize(QSize(LayoutTestController::maxViewWidth, LayoutTestController::maxViewHeight));
// clean up cache by resetting quota.
qint64 quota = webPage()->settings()->offlineWebApplicationCacheQuota();
@@ -687,10 +713,18 @@ static QString dumpHistoryItem(const QWebHistoryItem& item, int indent, bool cur
result.append(url);
}
- // FIXME: Wrong, need (private?) API for determining this.
- result.append(QLatin1String(" **nav target**"));
+ QString target = DumpRenderTreeSupportQt::historyItemTarget(item);
+ if (!target.isEmpty())
+ result.append(QString(QLatin1String(" (in frame \"%1\")")).arg(target));
+
+ if (DumpRenderTreeSupportQt::isTargetItem(item))
+ result.append(QLatin1String(" **nav target**"));
result.append(QLatin1String("\n"));
+ QList<QWebHistoryItem> children = DumpRenderTreeSupportQt::getChildHistoryItems(item);
+ for (int i = 0; i < children.size(); ++i)
+ result += dumpHistoryItem(children.at(i), 12, false);
+
return result;
}
@@ -920,9 +954,9 @@ void DumpRenderTree::checkPermission(const QUrl& url, NotificationPermission& pe
permission = m_controller->checkDesktopNotificationPermission(url.scheme() + "://" + url.host()) ? NotificationAllowed : NotificationDenied;
}
-void DumpRenderTree::requestPermission(QWebPage* page, const QString& origin)
+void DumpRenderTree::requestPermission(const QString& origin)
{
- DumpRenderTreeSupportQt::allowNotificationForOrigin(page, origin);
+ DumpRenderTreeSupportQt::allowNotificationForOrigin(origin);
}
#if defined(Q_WS_X11)
diff --git a/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.h b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.h
index 3fa4485..2ec972a 100644
--- a/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.h
+++ b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.h
@@ -41,6 +41,8 @@
#endif
#include "../../../WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.h"
+#include <qgraphicsview.h>
+#include <qgraphicswebview.h>
#include <qwebframe.h>
#include <qwebinspector.h>
#include <qwebpage.h>
@@ -80,6 +82,9 @@ public:
void setSingleFileMode(bool flag) { m_singleFileMode = flag; }
bool isSingleFileMode() { return m_singleFileMode; }
+ void setGraphicsBased(bool flag) { m_graphicsBased = flag; }
+ bool isGraphicsBased() { return m_graphicsBased; }
+
void setDumpPixels(bool);
void closeRemainingWindows();
@@ -115,7 +120,7 @@ public Q_SLOTS:
void statusBarMessage(const QString& message);
void windowCloseRequested();
void checkPermission(const QUrl&, NotificationPermission&);
- void requestPermission(QWebPage* page, const QString&);
+ void requestPermission(const QString&);
Q_SIGNALS:
void quit();
@@ -135,7 +140,7 @@ private:
QString m_expectedHash;
WebPage *m_page;
- QWebView* m_mainView;
+ QWidget* m_mainView;
EventSender *m_eventSender;
TextInputController *m_textInputController;
@@ -147,6 +152,7 @@ private:
QList<QObject*> windows;
bool m_enableTextOutput;
bool m_singleFileMode;
+ bool m_graphicsBased;
QString m_persistentStoragePath;
};
@@ -185,6 +191,7 @@ public:
public slots:
bool shouldInterruptJavaScript() { return false; }
+ bool allowGeolocationRequest(QWebFrame *frame);
protected:
bool acceptNavigationRequest(QWebFrame* frame, const QNetworkRequest& request, NavigationType type);
@@ -202,6 +209,18 @@ private:
DumpRenderTree *m_drt;
};
+class WebViewGraphicsBased : public QGraphicsView {
+ Q_OBJECT
+
+public:
+ WebViewGraphicsBased(QWidget* parent);
+ QGraphicsWebView* graphicsView() const { return m_item; }
+ void setPage(QWebPage* page) { m_item->setPage(page); }
+
+private:
+ QGraphicsWebView* m_item;
+};
+
}
#endif
diff --git a/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp b/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp
index a548a63..7ec505f 100644
--- a/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp
+++ b/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp
@@ -29,8 +29,7 @@
#include "config.h"
#include "EventSenderQt.h"
-//#include <QtDebug>
-
+#include <QGraphicsSceneMouseEvent>
#include <QtTest/QtTest>
#define KEYCODE_DEL 127
@@ -111,10 +110,16 @@ void EventSender::mouseDown(int button)
m_mouseButtons |= mouseButton;
// qDebug() << "EventSender::mouseDown" << frame;
- QMouseEvent* event;
- event = new QMouseEvent((m_clickCount == 2) ? QEvent::MouseButtonDblClick :
+ QEvent* event;
+ if (isGraphicsBased()) {
+ event = createGraphicsSceneMouseEvent((m_clickCount == 2) ?
+ QEvent::GraphicsSceneMouseDoubleClick : QEvent::GraphicsSceneMousePress,
+ m_mousePos, m_mousePos, mouseButton, m_mouseButtons, Qt::NoModifier);
+ } else {
+ event = new QMouseEvent((m_clickCount == 2) ? QEvent::MouseButtonDblClick :
QEvent::MouseButtonPress, m_mousePos, m_mousePos,
mouseButton, m_mouseButtons, Qt::NoModifier);
+ }
sendOrQueueEvent(event);
@@ -146,7 +151,15 @@ void EventSender::mouseUp(int button)
m_mouseButtons &= ~mouseButton;
// qDebug() << "EventSender::mouseUp" << frame;
- QMouseEvent* event = new QMouseEvent(QEvent::MouseButtonRelease, m_mousePos, m_mousePos, mouseButton, m_mouseButtons, Qt::NoModifier);
+ QEvent* event;
+ if (isGraphicsBased()) {
+ event = createGraphicsSceneMouseEvent(QEvent::GraphicsSceneMouseRelease,
+ m_mousePos, m_mousePos, mouseButton, m_mouseButtons, Qt::NoModifier);
+ } else {
+ event = new QMouseEvent(QEvent::MouseButtonRelease,
+ m_mousePos, m_mousePos, mouseButton, m_mouseButtons, Qt::NoModifier);
+ }
+
sendOrQueueEvent(event);
}
@@ -154,7 +167,16 @@ void EventSender::mouseMoveTo(int x, int y)
{
// qDebug() << "EventSender::mouseMoveTo" << x << y;
m_mousePos = QPoint(x, y);
- QMouseEvent* event = new QMouseEvent(QEvent::MouseMove, m_mousePos, m_mousePos, Qt::NoButton, m_mouseButtons, Qt::NoModifier);
+
+ QEvent* event;
+ if (isGraphicsBased()) {
+ event = createGraphicsSceneMouseEvent(QEvent::GraphicsSceneMouseMove,
+ m_mousePos, m_mousePos, Qt::NoButton, m_mouseButtons, Qt::NoModifier);
+ } else {
+ event = new QMouseEvent(QEvent::MouseMove,
+ m_mousePos, m_mousePos, Qt::NoButton, m_mouseButtons, Qt::NoModifier);
+ }
+
sendOrQueueEvent(event);
}
@@ -306,19 +328,19 @@ void EventSender::keyDown(const QString& string, const QStringList& modifiers, u
}
}
QKeyEvent event(QEvent::KeyPress, code, modifs, s);
- QApplication::sendEvent(m_page, &event);
+ sendEvent(m_page, &event);
QKeyEvent event2(QEvent::KeyRelease, code, modifs, s);
- QApplication::sendEvent(m_page, &event2);
+ sendEvent(m_page, &event2);
}
void EventSender::contextClick()
{
QMouseEvent event(QEvent::MouseButtonPress, m_mousePos, Qt::RightButton, Qt::RightButton, Qt::NoModifier);
- QApplication::sendEvent(m_page, &event);
+ sendEvent(m_page, &event);
QMouseEvent event2(QEvent::MouseButtonRelease, m_mousePos, Qt::RightButton, Qt::RightButton, Qt::NoModifier);
- QApplication::sendEvent(m_page, &event2);
+ sendEvent(m_page, &event2);
QContextMenuEvent event3(QContextMenuEvent::Mouse, m_mousePos);
- QApplication::sendEvent(m_page->view(), &event3);
+ sendEvent(m_page->view(), &event3);
}
void EventSender::scheduleAsynchronousClick()
@@ -431,7 +453,7 @@ void EventSender::sendTouchEvent(QEvent::Type type)
#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
QTouchEvent event(type, QTouchEvent::TouchScreen, m_touchModifiers);
event.setTouchPoints(m_touchPoints);
- QApplication::sendEvent(m_page, &event);
+ sendEvent(m_page, &event);
QList<QTouchEvent::TouchPoint>::Iterator it = m_touchPoints.begin();
while (it != m_touchPoints.end()) {
if (it->state() == Qt::TouchPointReleased)
@@ -493,7 +515,7 @@ void EventSender::sendOrQueueEvent(QEvent* event)
// 3. A call to mouseMoveTo while the mouse button is pressed could initiate a drag operation, and that does not return until mouseUp is processed.
// To be safe and avoid a deadlock, this event is queued.
if (endOfQueue == startOfQueue && !eventQueue[endOfQueue].m_delay && (!(m_mouseButtonPressed && (m_eventLoop && event->type() == QEvent::MouseButtonRelease)))) {
- QApplication::sendEvent(m_page->view(), event);
+ sendEvent(m_page->view(), event);
delete event;
return;
}
@@ -541,13 +563,16 @@ bool EventSender::eventFilter(QObject* watched, QEvent* event)
case QEvent::Leave:
return true;
case QEvent::MouseButtonPress:
+ case QEvent::GraphicsSceneMousePress:
m_mouseButtonPressed = true;
break;
case QEvent::MouseMove:
+ case QEvent::GraphicsSceneMouseMove:
if (m_mouseButtonPressed)
m_drag = true;
break;
case QEvent::MouseButtonRelease:
+ case QEvent::GraphicsSceneMouseRelease:
m_mouseButtonPressed = false;
m_drag = false;
break;
@@ -562,3 +587,24 @@ void EventSender::timerEvent(QTimerEvent* ev)
{
m_clickTimer.stop();
}
+
+QGraphicsSceneMouseEvent* EventSender::createGraphicsSceneMouseEvent(QEvent::Type type, const QPoint& pos, const QPoint& screenPos, Qt::MouseButton button, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
+{
+ QGraphicsSceneMouseEvent* event;
+ event = new QGraphicsSceneMouseEvent(type);
+ event->setPos(pos);
+ event->setScreenPos(screenPos);
+ event->setButton(button);
+ event->setButtons(buttons);
+ event->setModifiers(modifiers);
+
+ return event;
+}
+
+void EventSender::sendEvent(QObject* receiver, QEvent* event)
+{
+ if (WebCore::WebViewGraphicsBased* view = qobject_cast<WebCore::WebViewGraphicsBased*>(receiver))
+ view->scene()->sendEvent(view->graphicsView(), event);
+ else
+ QApplication::sendEvent(receiver, event);
+}
diff --git a/WebKitTools/DumpRenderTree/qt/EventSenderQt.h b/WebKitTools/DumpRenderTree/qt/EventSenderQt.h
index d5b45ac..51c8325 100644
--- a/WebKitTools/DumpRenderTree/qt/EventSenderQt.h
+++ b/WebKitTools/DumpRenderTree/qt/EventSenderQt.h
@@ -29,6 +29,9 @@
#ifndef EventSenderQt_h
#define EventSenderQt_h
+
+#include "DumpRenderTreeQt.h"
+
#include <QApplication>
#include <QBasicTimer>
#include <QEvent>
@@ -83,6 +86,11 @@ protected:
void timerEvent(QTimerEvent*);
private:
+ bool isGraphicsBased() const { return qobject_cast<WebCore::WebViewGraphicsBased*>(m_page->view()); }
+ QGraphicsSceneMouseEvent* createGraphicsSceneMouseEvent(QEvent::Type, const QPoint& pos, const QPoint& screenPos, Qt::MouseButton, Qt::MouseButtons, Qt::KeyboardModifiers);
+ void sendEvent(QObject* receiver, QEvent* event);
+
+private:
void sendTouchEvent(QEvent::Type);
void sendOrQueueEvent(QEvent*);
void replaySavedEvents(bool flush);
diff --git a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp
index 9079be2..8450376 100644
--- a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp
+++ b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp
@@ -410,7 +410,7 @@ void LayoutTestController::setMainFrameIsFirstResponder(bool isFirst)
void LayoutTestController::setJavaScriptCanAccessClipboard(bool enable)
{
- m_drt->webPage()->settings()->setAttribute(QWebSettings::JavaScriptCanAccessClipboard, enable);
+ m_drt->webPage()->settings()->setAttribute(QWebSettings::JavascriptCanAccessClipboard, enable);
}
void LayoutTestController::setXSSAuditorEnabled(bool enable)
@@ -513,6 +513,8 @@ void LayoutTestController::overridePreference(const QString& name, const QVarian
setCaretBrowsingEnabled(value.toBool());
else if (name == "WebKitPluginsEnabled")
settings->setAttribute(QWebSettings::PluginsEnabled, value.toBool());
+ else if (name == "WebKitWebGLEnabled")
+ settings->setAttribute(QWebSettings::WebGLEnabled, value.toBool());
else
printf("ERROR: LayoutTestController::overridePreference() does not support the '%s' preference\n",
name.toLatin1().data());
@@ -564,8 +566,7 @@ int LayoutTestController::numberOfPages(float width, float height)
bool LayoutTestController::callShouldCloseOnWebView()
{
- // FIXME: Implement for testing fix for https://bugs.webkit.org/show_bug.cgi?id=27481
- return false;
+ return DumpRenderTreeSupportQt::shouldClose(m_drt->webPage()->mainFrame());
}
void LayoutTestController::setScrollbarPolicy(const QString& orientation, const QString& policy)
@@ -645,5 +646,21 @@ void LayoutTestController::setEditingBehavior(const QString& editingBehavior)
DumpRenderTreeSupportQt::setEditingBehavior(m_drt->webPage(), editingBehavior);
}
+void LayoutTestController::setGeolocationPermission(bool allow)
+{
+ m_isGeolocationPermissionSet = true;
+ m_geolocationPermission = allow;
+}
+
+void LayoutTestController::setMockGeolocationError(int code, const QString& message)
+{
+ DumpRenderTreeSupportQt::setMockGeolocationError(code, message);
+}
+
+void LayoutTestController::setMockGeolocationPosition(double latitude, double longitude, double accuracy)
+{
+ DumpRenderTreeSupportQt::setMockGeolocationPosition(latitude, longitude, accuracy);
+}
+
const unsigned LayoutTestController::maxViewWidth = 800;
const unsigned LayoutTestController::maxViewHeight = 600;
diff --git a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h
index d7bb839..a041ad0 100644
--- a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h
+++ b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h
@@ -180,6 +180,15 @@ public slots:
int pageNumberForElementById(const QString& id, float width = 0, float height = 0);
int numberOfPages(float width = maxViewWidth, float height = maxViewHeight);
bool callShouldCloseOnWebView();
+ // For now, this is a no-op. This may change depending on outcome of
+ // https://bugs.webkit.org/show_bug.cgi?id=33333
+ void setCallCloseOnWebViews() {}
+
+ void setMockGeolocationError(int code, const QString& message);
+ void setMockGeolocationPosition(double latitude, double longitude, double accuracy);
+ void setGeolocationPermission(bool allow);
+ bool isGeolocationPermissionSet() const { return m_isGeolocationPermissionSet; }
+ bool geolocationPermission() const { return m_geolocationPermission; }
/*
Policy values: 'on', 'auto' or 'off'.
@@ -212,6 +221,8 @@ private:
bool m_handleErrorPages;
bool m_loadFinished;
bool m_globalFlag;
+ bool m_isGeolocationPermissionSet;
+ bool m_geolocationPermission;
QUrl m_userStyleSheetLocation;
QBasicTimer m_timeoutTimer;
diff --git a/WebKitTools/DumpRenderTree/win/AccessibilityUIElementWin.cpp b/WebKitTools/DumpRenderTree/win/AccessibilityUIElementWin.cpp
index 9f00ae4..6aef32e 100644
--- a/WebKitTools/DumpRenderTree/win/AccessibilityUIElementWin.cpp
+++ b/WebKitTools/DumpRenderTree/win/AccessibilityUIElementWin.cpp
@@ -100,6 +100,12 @@ AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
return 0;
}
+AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
+{
+ // FIXME: implement
+ return 0;
+}
+
AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
{
COMPtr<IDispatch> child;
diff --git a/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp
index b22f342..1ed54d5 100644
--- a/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp
+++ b/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp
@@ -969,8 +969,10 @@ static void runTest(const string& testPathOrURL)
DispatchMessage(&msg);
}
- if (shouldEnableDeveloperExtras(pathOrURL.c_str()))
+ if (shouldEnableDeveloperExtras(pathOrURL.c_str())) {
gLayoutTestController->closeWebInspector();
+ gLayoutTestController->setDeveloperExtrasEnabled(false);
+ }
resetWebViewToConsistentStateBeforeTesting();