RTL non-native <select> buttons should have arrows on the left
authordino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 Apr 2016 01:53:31 +0000 (01:53 +0000)
committerdino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 Apr 2016 01:53:31 +0000 (01:53 +0000)
https://bugs.webkit.org/show_bug.cgi?id=157112
<rdar://problem/25894441>

Reviewed by Simon Fraser.

Source/WebCore:

The <select> elements that are completely rendered by WebCore
(i.e. not the native controls) always assumed that they
were left-to-right.

This change allows the button to handle both directions,
swapping the side the little arrows are rendered on, as
well as the padding of the text label.

Test: fast/forms/select-non-native-rendering-direction.html

* rendering/RenderMenuList.cpp:
(RenderMenuList::clientPaddingLeft): This must take into account
the direction of the element.
(RenderMenuList::clientPaddingRight): Ditto.
* rendering/RenderThemeMac.mm: Change the left and right constants
to use the terms before and after.
(WebCore::RenderThemeMac::paintMenuListButtonDecorations): The left
and right positions must take the direction into account, which
means different calculations.
(WebCore::RenderThemeMac::popupInternalPaddingBox): Similarly for
the padding that is used to position the text label.

LayoutTests:

New test that checks the layout of WebCore-drawn <select>
elements in right-to-left mode.

* fast/forms/select-non-native-rendering-direction.html: Added.
* platform/mac/fast/forms/select-non-native-rendering-direction-expected.png: Added.
* platform/mac/fast/forms/select-non-native-rendering-direction-expected.txt: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@200165 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/forms/select-non-native-rendering-direction.html [new file with mode: 0644]
LayoutTests/platform/mac/fast/forms/select-non-native-rendering-direction-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/forms/select-non-native-rendering-direction-expected.txt [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderMenuList.cpp
Source/WebCore/rendering/RenderThemeMac.mm

index 5827682..2b2ae21 100644 (file)
@@ -1,3 +1,18 @@
+2016-04-27  Dean Jackson  <dino@apple.com>
+
+        RTL non-native <select> buttons should have arrows on the left
+        https://bugs.webkit.org/show_bug.cgi?id=157112
+        <rdar://problem/25894441>
+
+        Reviewed by Simon Fraser.
+
+        New test that checks the layout of WebCore-drawn <select>
+        elements in right-to-left mode.
+
+        * fast/forms/select-non-native-rendering-direction.html: Added.
+        * platform/mac/fast/forms/select-non-native-rendering-direction-expected.png: Added.
+        * platform/mac/fast/forms/select-non-native-rendering-direction-expected.txt: Added.
+
 2016-04-27  Brady Eidson  <beidson@apple.com>
 
         Modern IDB: Implement native IDBFactory.getAllDatabaseNames for WebInspector.
diff --git a/LayoutTests/fast/forms/select-non-native-rendering-direction.html b/LayoutTests/fast/forms/select-non-native-rendering-direction.html
new file mode 100644 (file)
index 0000000..f805a85
--- /dev/null
@@ -0,0 +1,116 @@
+<style>
+select {
+    border: 1px solid black;
+}
+</style>
+<div>
+Left to right select:
+<select>
+<option>Alabama</option>
+<option>Alaska</option>
+<option>Arizona</option>
+<option>Arkansas</option>
+<option>California</option>
+<option>Colorado</option>
+<option>Connecticut</option>
+<option>Delaware</option>
+<option>Florida</option>
+<option>Georgia</option>
+<option>Hawaii</option>
+<option>Idaho</option>
+<option>Illinois</option>
+<option>Indiana</option>
+<option>Iowa</option>
+<option>Kansas</option>
+<option>Kentucky</option>
+<option>Louisiana</option>
+<option>Maine</option>
+<option>Maryland</option>
+<option>Massachusetts</option>
+<option>Michigan</option>
+<option>Minnesota</option>
+<option>Mississippi</option>
+<option>Missouri</option>
+<option>Montana</option>
+<option>Nebraska</option>
+<option>Nevada</option>
+<option>New Hampshire</option>
+<option>New Jersey</option>
+<option>New Mexico</option>
+<option>New York</option>
+<option>North Carolina</option>
+<option>North Dakota</option>
+<option>Ohio</option>
+<option>Oklahoma</option>
+<option>Oregon</option>
+<option>Pennsylvania</option>
+<option>Rhode Island</option>
+<option>South Carolina</option>
+<option>South Dakota</option>
+<option>Tennessee</option>
+<option>Texas</option>
+<option>Utah</option>
+<option>Vermont</option>
+<option>Virginia</option>
+<option>Washington</option>
+<option>West Virginia</option>
+<option>Wisconsin</option>
+<option>Wyoming</option>
+</select>
+</div>
+
+<div dir="rtl">
+Right to left select:
+<select>
+<option>Alabama</option>
+<option>Alaska</option>
+<option>Arizona</option>
+<option>Arkansas</option>
+<option>California</option>
+<option>Colorado</option>
+<option>Connecticut</option>
+<option>Delaware</option>
+<option>Florida</option>
+<option>Georgia</option>
+<option>Hawaii</option>
+<option>Idaho</option>
+<option>Illinois</option>
+<option>Indiana</option>
+<option>Iowa</option>
+<option>Kansas</option>
+<option>Kentucky</option>
+<option>Louisiana</option>
+<option>Maine</option>
+<option>Maryland</option>
+<option>Massachusetts</option>
+<option>Michigan</option>
+<option>Minnesota</option>
+<option>Mississippi</option>
+<option>Missouri</option>
+<option>Montana</option>
+<option>Nebraska</option>
+<option>Nevada</option>
+<option>New Hampshire</option>
+<option>New Jersey</option>
+<option>New Mexico</option>
+<option>New York</option>
+<option>North Carolina</option>
+<option>North Dakota</option>
+<option>Ohio</option>
+<option>Oklahoma</option>
+<option>Oregon</option>
+<option>Pennsylvania</option>
+<option>Rhode Island</option>
+<option>South Carolina</option>
+<option>South Dakota</option>
+<option>Tennessee</option>
+<option>Texas</option>
+<option>Utah</option>
+<option>Vermont</option>
+<option>Virginia</option>
+<option>Washington</option>
+<option>West Virginia</option>
+<option>Wisconsin</option>
+<option>Wyoming</option>
+</select>
+</div>
diff --git a/LayoutTests/platform/mac/fast/forms/select-non-native-rendering-direction-expected.png b/LayoutTests/platform/mac/fast/forms/select-non-native-rendering-direction-expected.png
new file mode 100644 (file)
index 0000000..81665ca
Binary files /dev/null and b/LayoutTests/platform/mac/fast/forms/select-non-native-rendering-direction-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/forms/select-non-native-rendering-direction-expected.txt b/LayoutTests/platform/mac/fast/forms/select-non-native-rendering-direction-expected.txt
new file mode 100644 (file)
index 0000000..5beb90c
--- /dev/null
@@ -0,0 +1,22 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {DIV} at (0,0) size 784x22
+        RenderText {#text} at (0,1) size 127x18
+          text run at (0,1) width 127: "Left to right select: "
+        RenderMenuList {SELECT} at (128,2) size 116x18 [bgcolor=#FFFFFF] [border: (1px solid #000000)]
+          RenderBlock (anonymous) at (1,1) size 113x16
+            RenderText at (8,1) size 47x13
+              text run at (8,1) width 47: "Alabama"
+        RenderText {#text} at (0,0) size 0x0
+      RenderBlock {DIV} at (0,22) size 784x22
+        RenderText {#text} at (657,1) size 127x18
+          text run at (657,1) width 10 RTL: ": "
+          text run at (666,1) width 118: "Right to left select"
+        RenderMenuList {SELECT} at (540,2) size 116x18 [bgcolor=#FFFFFF] [border: (1px solid #000000)]
+          RenderBlock (anonymous) at (1,1) size 113x16
+            RenderText at (58,1) size 47x13
+              text run at (58,1) width 47: "Alabama"
+        RenderText {#text} at (0,0) size 0x0
index 2b4309d..1619fda 100644 (file)
@@ -1,3 +1,33 @@
+2016-04-27  Dean Jackson  <dino@apple.com>
+
+        RTL non-native <select> buttons should have arrows on the left
+        https://bugs.webkit.org/show_bug.cgi?id=157112
+        <rdar://problem/25894441>
+
+        Reviewed by Simon Fraser.
+
+        The <select> elements that are completely rendered by WebCore
+        (i.e. not the native controls) always assumed that they
+        were left-to-right.
+
+        This change allows the button to handle both directions,
+        swapping the side the little arrows are rendered on, as
+        well as the padding of the text label.
+
+        Test: fast/forms/select-non-native-rendering-direction.html
+
+        * rendering/RenderMenuList.cpp:
+        (RenderMenuList::clientPaddingLeft): This must take into account
+        the direction of the element.
+        (RenderMenuList::clientPaddingRight): Ditto.
+        * rendering/RenderThemeMac.mm: Change the left and right constants
+        to use the terms before and after.
+        (WebCore::RenderThemeMac::paintMenuListButtonDecorations): The left
+        and right positions must take the direction into account, which
+        means different calculations.
+        (WebCore::RenderThemeMac::popupInternalPaddingBox): Similarly for
+        the padding that is used to position the text label.
+
 2016-04-27  Simon Fraser  <simon.fraser@apple.com>
 
         CSS and SVG animations should run at 60fps
index 30da424..4db33a0 100644 (file)
@@ -591,24 +591,27 @@ int RenderMenuList::clientInsetRight() const
     return 0;
 }
 
-LayoutUnit RenderMenuList::clientPaddingLeft() const
-{
-    return paddingLeft() + m_innerBlock->paddingLeft();
-}
-
 const int endOfLinePadding = 2;
-LayoutUnit RenderMenuList::clientPaddingRight() const
+
+LayoutUnit RenderMenuList::clientPaddingLeft() const
 {
-    if (style().appearance() == MenulistPart || style().appearance() == MenulistButtonPart) {
+    if ((style().appearance() == MenulistPart || style().appearance() == MenulistButtonPart) && style().direction() == RTL) {
         // For these appearance values, the theme applies padding to leave room for the
         // drop-down button. But leaving room for the button inside the popup menu itself
         // looks strange, so we return a small default padding to avoid having a large empty
         // space appear on the side of the popup menu.
         return endOfLinePadding;
     }
-
     // If the appearance isn't MenulistPart, then the select is styled (non-native), so
     // we want to return the user specified padding.
+    return paddingLeft() + m_innerBlock->paddingLeft();
+}
+
+LayoutUnit RenderMenuList::clientPaddingRight() const
+{
+    if ((style().appearance() == MenulistPart || style().appearance() == MenulistButtonPart) && style().direction() == LTR)
+        return endOfLinePadding;
+
     return paddingRight() + m_innerBlock->paddingRight();
 }
 
index 564d505..0a22119 100644 (file)
@@ -1161,8 +1161,8 @@ const float baseFontSize = 11.0f;
 const float baseArrowHeight = 4.0f;
 const float baseArrowWidth = 5.0f;
 const float baseSpaceBetweenArrows = 2.0f;
-const int arrowPaddingLeft = 6;
-const int arrowPaddingRight = 6;
+const int arrowPaddingBefore = 6;
+const int arrowPaddingAfter = 6;
 const int paddingBeforeSeparator = 4;
 const int baseBorderRadius = 5;
 const int styledPopupPaddingLeft = 8;
@@ -1278,6 +1278,7 @@ void RenderThemeMac::paintMenuListButtonGradients(const RenderObject& o, const P
 
 bool RenderThemeMac::paintMenuListButtonDecorations(const RenderBox& renderer, const PaintInfo& paintInfo, const FloatRect& rect)
 {
+    bool isRTL = renderer.style().direction() == RTL;
     IntRect bounds = IntRect(rect.x() + renderer.style().borderLeftWidth(),
         rect.y() + renderer.style().borderTopWidth(),
         rect.width() - renderer.style().borderLeftWidth() - renderer.style().borderRightWidth(),
@@ -1290,10 +1291,14 @@ bool RenderThemeMac::paintMenuListButtonDecorations(const RenderBox& renderer, c
     float centerY = bounds.y() + bounds.height() / 2.0f;
     float arrowHeight = baseArrowHeight * fontScale;
     float arrowWidth = baseArrowWidth * fontScale;
-    float leftEdge = bounds.maxX() - arrowPaddingRight * renderer.style().effectiveZoom() - arrowWidth;
+    float leftEdge;
+    if (isRTL)
+        leftEdge = bounds.x() + arrowPaddingAfter * renderer.style().effectiveZoom();
+    else
+        leftEdge = bounds.maxX() - arrowPaddingAfter * renderer.style().effectiveZoom() - arrowWidth;
     float spaceBetweenArrows = baseSpaceBetweenArrows * fontScale;
 
-    if (bounds.width() < arrowWidth + arrowPaddingLeft * renderer.style().effectiveZoom())
+    if (bounds.width() < arrowWidth + arrowPaddingBefore * renderer.style().effectiveZoom())
         return false;
 
     GraphicsContextStateSaver stateSaver(paintInfo.context());
@@ -1322,18 +1327,22 @@ bool RenderThemeMac::paintMenuListButtonDecorations(const RenderBox& renderer, c
 
     // FIXME: Should the separator thickness and space be scaled up by fontScale?
     int separatorSpace = 2; // Deliberately ignores zoom since it looks nicer if it stays thin.
-    int leftEdgeOfSeparator = static_cast<int>(leftEdge - arrowPaddingLeft * renderer.style().effectiveZoom()); // FIXME: Round?
+    int leftEdgeOfSeparator;
+    if (isRTL)
+        leftEdgeOfSeparator = static_cast<int>(roundf(leftEdge + arrowWidth + arrowPaddingBefore * renderer.style().effectiveZoom()));
+    else
+        leftEdgeOfSeparator = static_cast<int>(roundf(leftEdge - arrowPaddingBefore * renderer.style().effectiveZoom()));
 
     // Draw the separator to the left of the arrows
     paintInfo.context().setStrokeThickness(1); // Deliberately ignores zoom since it looks nicer if it stays thin.
     paintInfo.context().setStrokeStyle(SolidStroke);
     paintInfo.context().setStrokeColor(leftSeparatorColor);
     paintInfo.context().drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()),
-                                IntPoint(leftEdgeOfSeparator, bounds.maxY()));
+        IntPoint(leftEdgeOfSeparator, bounds.maxY()));
 
     paintInfo.context().setStrokeColor(rightSeparatorColor);
     paintInfo.context().drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()),
-                                IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.maxY()));
+        IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.maxY()));
     return false;
 }
 
@@ -1383,9 +1392,14 @@ LengthBox RenderThemeMac::popupInternalPaddingBox(const RenderStyle& style) cons
 
     if (style.appearance() == MenulistButtonPart) {
         float arrowWidth = baseArrowWidth * (style.fontSize() / baseFontSize);
+        float rightPadding = ceilf(arrowWidth + (arrowPaddingBefore + arrowPaddingAfter + paddingBeforeSeparator) * style.effectiveZoom());
+        float leftPadding = styledPopupPaddingLeft * style.effectiveZoom();
+        if (style.direction() == RTL)
+            std::swap(rightPadding, leftPadding);
         return { static_cast<int>(styledPopupPaddingTop * style.effectiveZoom()),
-            static_cast<int>(ceilf(arrowWidth + (arrowPaddingLeft + arrowPaddingRight + paddingBeforeSeparator) * style.effectiveZoom())),
-            static_cast<int>(styledPopupPaddingBottom * style.effectiveZoom()), static_cast<int>(styledPopupPaddingLeft * style.effectiveZoom()) };
+            static_cast<int>(rightPadding),
+            static_cast<int>(styledPopupPaddingBottom * style.effectiveZoom()),
+            static_cast<int>(leftPadding) };
     }
 
     return { 0, 0, 0, 0 };