diff --git a/mozilla/layout/html/base/src/nsSelectsAreaFrame.cpp b/mozilla/layout/html/base/src/nsSelectsAreaFrame.cpp
index 5ac39a7a0dd..e80156379a1 100644
--- a/mozilla/layout/html/base/src/nsSelectsAreaFrame.cpp
+++ b/mozilla/layout/html/base/src/nsSelectsAreaFrame.cpp
@@ -40,6 +40,7 @@
#include "nsIDOMHTMLOptionElement.h"
#include "nsIContent.h"
#include "nsIStyleContext.h"
+#include "nsListControlFrame.h"
nsresult
NS_NewSelectsAreaFrame(nsIPresShell* aShell, nsIFrame** aNewFrame, PRUint32 aFlags)
@@ -131,3 +132,18 @@ nsSelectsAreaFrame::GetFrameForPoint(nsIPresContext* aPresContext,
return result;
}
+
+NS_IMETHODIMP
+nsSelectsAreaFrame::Paint(nsIPresContext* aPresContext,
+ nsIRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect,
+ nsFramePaintLayer aWhichLayer,
+ PRUint32 aFlags)
+{
+ nsresult rv = nsAreaFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, aFlags);
+ // This assumes that that the ListControlFrame is the Parent
+ nsListControlFrame* listFrame = NS_STATIC_CAST(nsListControlFrame*, mParent);
+ listFrame->PaintFocus(aRenderingContext, aWhichLayer);
+
+ return rv;
+}
\ No newline at end of file
diff --git a/mozilla/layout/html/base/src/nsSelectsAreaFrame.h b/mozilla/layout/html/base/src/nsSelectsAreaFrame.h
index 52228850f6a..9b1a5e2c005 100644
--- a/mozilla/layout/html/base/src/nsSelectsAreaFrame.h
+++ b/mozilla/layout/html/base/src/nsSelectsAreaFrame.h
@@ -56,6 +56,11 @@ public:
NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, const nsPoint& aPoint, nsFramePaintLayer aWhichLayer, nsIFrame** aFrame);
+ NS_IMETHOD Paint(nsIPresContext* aPresContext,
+ nsIRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect,
+ nsFramePaintLayer aWhichLayer,
+ PRUint32 aFlags = 0);
protected:
PRBool IsOptionElement(nsIContent* aContent);
PRBool IsOptionElementFrame(nsIFrame *aFrame);
diff --git a/mozilla/layout/html/forms/src/nsListControlFrame.cpp b/mozilla/layout/html/forms/src/nsListControlFrame.cpp
index 58e61aa3549..66bfa1aeba6 100644
--- a/mozilla/layout/html/forms/src/nsListControlFrame.cpp
+++ b/mozilla/layout/html/forms/src/nsListControlFrame.cpp
@@ -51,6 +51,7 @@
#include "nsIDOMHTMLCollection.h"
#include "nsIDOMNSHTMLOptionCollectn.h"
#include "nsIDOMHTMLSelectElement.h"
+#include "nsIDOMNSHTMLSelectElement.h"
#include "nsIDOMHTMLOptionElement.h"
#include "nsIComboboxControlFrame.h"
#include "nsIViewManager.h"
@@ -82,6 +83,8 @@
#endif
#include "nsISelectElement.h"
#include "nsIPrivateDOMEvent.h"
+#include "nsCSSRendering.h"
+#include "nsILookAndFeel.h"
// Timer Includes
#include "nsITimer.h"
@@ -94,7 +97,9 @@ const PRInt32 kNothingSelected = -1;
const PRInt32 kMaxZ = 0x7fffffff; //XXX: Shouldn't there be a define somewhere for MaxInt for PRInt32
const PRInt32 kNoSizeSpecified = -1;
-// We now use the :checked pseudoclass for the option selected state
+
+nsListControlFrame * nsListControlFrame::mFocused = nsnull;
+
//---------------------------------------------------------
nsresult
@@ -522,6 +527,176 @@ nsListControlFrame::Paint(nsIPresContext* aPresContext,
}
+void nsListControlFrame::PaintFocus(nsIRenderingContext& aRC, nsFramePaintLayer aWhichLayer)
+{
+ if (NS_FRAME_PAINT_LAYER_FOREGROUND != aWhichLayer) return;
+
+ if (mFocused != this) return;
+
+ // The mEndSelectionIndex is what is currently being selected
+ // use the selected index if this is kNothingSelected
+ PRInt32 focusedIndex;
+ if (mEndSelectionIndex == kNothingSelected) {
+ GetSelectedIndex(&focusedIndex);
+ } else {
+ focusedIndex = mEndSelectionIndex;
+ }
+
+ nsIScrollableView * scrollableView;
+ GetScrollableView(scrollableView);
+ if (!scrollableView) return;
+
+ nsCOMPtr presShell;
+ mPresContext->GetShell(getter_AddRefs(presShell));
+ if (!presShell) return;
+
+ nsIFrame* containerFrame;
+ GetOptionsContainer(mPresContext, &containerFrame);
+ if (!containerFrame) return;
+
+ nsIFrame * childframe = nsnull;
+ nsresult result = NS_ERROR_FAILURE;
+
+ nsCOMPtr focusedContent;
+
+ nsCOMPtr selectNSElement(do_QueryInterface(mContent));
+ NS_ASSERTION(selectNSElement, "Can't be null");
+
+ nsCOMPtr selectElement(do_QueryInterface(mContent));
+ NS_ASSERTION(selectElement, "Can't be null");
+
+ // If we have a selected index then get that child frame
+ if (focusedIndex != kNothingSelected) {
+ focusedContent = getter_AddRefs(GetOptionContent(focusedIndex));
+ // otherwise we find the focusedContent's frame and scroll to it
+ if (focusedContent) {
+ result = presShell->GetPrimaryFrameFor(focusedContent, &childframe);
+ }
+ } else {
+ nsCOMPtr selectHTMLElement(do_QueryInterface(mContent));
+ NS_ASSERTION(selectElement, "Can't be null");
+
+ // Since there isn't a selected item we need to show a focus ring around the first
+ // non-disabled item and skip all the option group elements (nodes)
+ nsCOMPtr node;
+
+ PRUint32 length;
+ selectHTMLElement->GetLength(&length);
+ if (length) {
+ // find the first non-disabled item
+ PRBool isDisabled = PR_TRUE;
+ for (PRInt32 i=0;iItem(i, getter_AddRefs(node))) || !node) {
+ break;
+ }
+ if (NS_FAILED(selectElement->IsOptionDisabled(i, &isDisabled))) {
+ break;
+ }
+ if (isDisabled) {
+ node = nsnull;
+ } else {
+ break;
+ }
+ }
+ if (!node) {
+ return;
+ }
+ }
+
+ // if we found a node use, if not get the first child (this is for empty selects)
+ if (node) {
+ focusedContent = do_QueryInterface(node);
+ result = presShell->GetPrimaryFrameFor(focusedContent, &childframe);
+ }
+ if (!childframe) {
+ // The only way we can get right here is that there are no options
+ // and we need to get the dummy frame so it has the focus ring
+ result = containerFrame->FirstChild(mPresContext, nsnull, &childframe);
+ }
+ }
+
+ if (NS_FAILED(result) || !childframe) return;
+
+ const nsIView * clippedView;
+ scrollableView->GetClipView(&clippedView);
+ if (!clippedView) return;
+
+ nscoord x;
+ nscoord y;
+ scrollableView->GetScrollPosition(x,y);
+ // get the clipped rect
+ nsRect rect;
+ clippedView->GetBounds(rect);
+
+ // now move it by the offset of the scroll position
+ rect.x = 0;
+ rect.y = 0;
+ rect.MoveBy(x,y);
+
+ // get the child rect
+ nsRect fRect;
+ childframe->GetRect(fRect);
+
+ nsRect clipRect;
+ containerFrame->GetRect(clipRect);
+ clipRect.x = 0;
+ clipRect.y = 0;
+
+ PRBool clipEmpty;
+ aRC.PushState();
+ aRC.SetClipRect(clipRect, nsClipCombine_kReplace, clipEmpty);
+
+ // adjust position is it is a child of a option group
+ if (focusedContent) {
+ nsRect optRect(0,0,0,0);
+ nsCOMPtr parentContent;
+ focusedContent->GetParent(*getter_AddRefs(parentContent));
+ nsCOMPtr optGroup(do_QueryInterface(parentContent));
+ if (optGroup) {
+ nsIFrame * optFrame;
+ result = presShell->GetPrimaryFrameFor(parentContent, &optFrame);
+ if (NS_SUCCEEDED(result) && optFrame) {
+ optFrame->GetRect(optRect);
+ }
+ }
+ fRect.y += optRect.y;
+ }
+
+ PRBool lastItemIsSelected = PR_FALSE;
+ nsCOMPtr node;
+ if (NS_SUCCEEDED(selectNSElement->Item(focusedIndex, getter_AddRefs(node)))) {
+ nsCOMPtr domOpt(do_QueryInterface(node));
+ if (domOpt) {
+ selectElement->IsOptionSelected(domOpt, &lastItemIsSelected);
+ }
+ }
+
+ // set up back stop colors and then ask L&F service for the real colors
+ nscolor color;
+ nsCOMPtr lookAndFeel;
+ mPresContext->GetLookAndFeel(getter_AddRefs(lookAndFeel));
+ if (lookAndFeel){
+ lookAndFeel->GetColor(lastItemIsSelected?nsILookAndFeel::eColor_WidgetSelectForeground:nsILookAndFeel::eColor_WidgetSelectBackground, color);
+ } else {
+ // Use some backstop colors if for some reason we don't have a L&F object
+ color = lastItemIsSelected? NS_RGB(245,219,149) : NS_RGB(0,0,0);
+ }
+
+ float p2t;
+ mPresContext->GetScaledPixelsToTwips(&p2t);
+ nscoord onePixelInTwips = NSToCoordRound(p2t);
+
+ nsRect dirty;
+ nscolor colors[] = {color, color, color, color};
+ PRUint8 borderStyle[] = {NS_STYLE_BORDER_STYLE_DOTTED, NS_STYLE_BORDER_STYLE_DOTTED, NS_STYLE_BORDER_STYLE_DOTTED, NS_STYLE_BORDER_STYLE_DOTTED};
+ nsRect innerRect = fRect;
+ innerRect.Deflate(nsSize(onePixelInTwips, onePixelInTwips));
+ nsCSSRendering::DrawDashedSides(0, aRC, dirty, borderStyle, colors, fRect, innerRect, 0, nsnull);
+
+ aRC.PopState(clipEmpty);
+
+}
+
//---------------------------------------------------------
// Frames are not refcounted, no need to AddRef
NS_IMETHODIMP
@@ -1831,7 +2006,18 @@ nsListControlFrame::GetName(nsAString* aResult)
void
nsListControlFrame::SetFocus(PRBool aOn, PRBool aRepaint)
{
- // XXX:TODO Make set focus work
+ if (aOn) {
+ PRInt32 selectedIndex;
+ GetSelectedIndex(&selectedIndex);
+ ScrollToIndex(selectedIndex);
+ mFocused = this;
+ } else {
+ mFocused = nsnull;
+ }
+
+ // Make sure the SelectArea frame gets painted
+ Invalidate(mPresContext, nsRect(0,0,mRect.width,mRect.height), PR_TRUE);
+
}
//---------------------------------------------------------
@@ -3311,6 +3497,10 @@ nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent)
presShell->FlushPendingNotifications(PR_FALSE);
}
REFLOW_DEBUG_MSG2(" After: %d\n", newIndex);
+
+ // Make sure the SelectArea frame gets painted
+ Invalidate(mPresContext, nsRect(0,0,mRect.width,mRect.height), PR_TRUE);
+
} else {
REFLOW_DEBUG_MSG(" After: SKIPPED it\n");
}
diff --git a/mozilla/layout/html/forms/src/nsListControlFrame.h b/mozilla/layout/html/forms/src/nsListControlFrame.h
index e6c93e4d526..49b3b4cd391 100644
--- a/mozilla/layout/html/forms/src/nsListControlFrame.h
+++ b/mozilla/layout/html/forms/src/nsListControlFrame.h
@@ -320,6 +320,8 @@ public:
// Helper
void SetPassId(PRInt16 aId) { mPassId = aId; }
+ void PaintFocus(nsIRenderingContext& aRC, nsFramePaintLayer aWhichLayer);
+
protected:
nsresult IsOptionDisabled(PRInt32 anIndex, PRBool &aIsDisabled);
@@ -422,6 +424,8 @@ protected:
nsSize mCachedUnconstrainedSize;
nsSize mCachedAvailableSize;
+ static nsListControlFrame * mFocused;
+
#ifdef DO_REFLOW_COUNTER
PRInt32 mReflowId;
#endif