Bug 1360500 - Allow custom colors on find selection type selections. r=jaws,masayuki,smaug

This patch implements chrome-only Selection#setColors and
Selection#resetColors methods, and use it to set the background color of
the preferences search highlight.

MozReview-Commit-ID: 2U92aBCAyeh

--HG--
extra : rebase_source : b07af1f37309d8184584b298a720cd5c1382929a
This commit is contained in:
Timothy Guan-tin Chien 2017-05-10 10:48:50 -04:00
Родитель b92dd9bc28
Коммит 1d08bd439b
8 изменённых файлов: 247 добавлений и 8 удалений

Просмотреть файл

@ -12,6 +12,7 @@ var gSearchResultsPane = {
init() {
let controller = this.getSelectionController();
this.findSelection = controller.getSelection(Ci.nsISelectionController.SELECTION_FIND);
this.findSelection.setColors("currentColor", "#ffe900", "currentColor", "#540ead");
this.searchResultsCategory = document.getElementById("category-search-results");
this.searchInput = document.getElementById("searchInput");

Просмотреть файл

@ -161,5 +161,35 @@ interface nsISelectionPrivate : nsISelection
* PR_FALSE if the new language is left-to-right.
*/
[noscript] void selectionLanguageChange(in boolean langRTL);
/**
* setColors() sets custom colors for the selection.
* Currently, this is supported only when the selection type is SELECTION_FIND.
* Otherwise, throws an exception.
*
* @param aForegroundColor The foreground color of the selection.
* If this is "currentColor", foreground color
* isn't changed by this selection.
* @param aBackgroundColor The background color of the selection.
* If this is "transparent", background color is
* never painted.
* @param aAltForegroundColor The alternative foreground color of the
* selection.
* If aBackgroundColor doesn't have sufficient
* contrast with its around or foreground color
* if "currentColor" is specified, alternative
* colors are used if it have higher contrast.
* @param aAltBackgroundColor The alternative background color of the
* selection.
*/
void setColors(in DOMString aForegroundColor,
in DOMString aBackgroundColor,
in DOMString aAltForegroundColor,
in DOMString aAltBackgroundColor);
/**
* resetColors() forget the customized colors which were set by setColors().
*/
void resetColors();
};

Просмотреть файл

@ -90,4 +90,11 @@ partial interface Selection {
[ChromeOnly,Throws]
void scrollIntoView(short aRegion, boolean aIsSynchronous, short aVPercent, short aHPercent);
[ChromeOnly,Throws]
void setColors(DOMString aForegroundColor, DOMString aBackgroundColor,
DOMString aAltForegroundColor, DOMString aAltBackgroundColor);
[ChromeOnly,Throws]
void resetColors();
};

Просмотреть файл

@ -30,6 +30,7 @@ class nsIHTMLEditor;
class nsFrameSelection;
class nsPIDOMWindowOuter;
struct SelectionDetails;
struct SelectionCustomColors;
class nsCopySupport;
class nsHTMLCopyEncoder;
@ -251,6 +252,12 @@ public:
int16_t aVPercent, int16_t aHPercent,
mozilla::ErrorResult& aRv);
void SetColors(const nsAString& aForeColor, const nsAString& aBackColor,
const nsAString& aAltForeColor, const nsAString& aAltBackColor,
mozilla::ErrorResult& aRv);
void ResetColors(mozilla::ErrorResult& aRv);
// Non-JS callers should use the following methods.
void Collapse(nsINode& aNode, uint32_t aOffset, mozilla::ErrorResult& aRv);
void CollapseToStart(mozilla::ErrorResult& aRv);
@ -284,6 +291,8 @@ public:
mSelectionType = aSelectionType;
}
SelectionCustomColors* GetCustomColors() const { return mCustomColors.get(); }
nsresult NotifySelectionListeners(bool aCalledByJS);
nsresult NotifySelectionListeners();
@ -418,9 +427,11 @@ private:
RefPtr<nsAutoScrollTimer> mAutoScrollTimer;
nsCOMArray<nsISelectionListener> mSelectionListeners;
nsRevocableEventPtr<ScrollSelectionIntoViewEvent> mScrollEvent;
CachedOffsetForFrame *mCachedOffsetForFrame;
CachedOffsetForFrame* mCachedOffsetForFrame;
nsDirection mDirection;
SelectionType mSelectionType;
UniquePtr<SelectionCustomColors> mCustomColors;
/**
* True if the current selection operation was initiated by user action.
* It determines whether we exclude -moz-user-select:none nodes or not,

Просмотреть файл

@ -45,6 +45,24 @@ struct SelectionDetails
mozilla::UniquePtr<SelectionDetails> mNext;
};
struct SelectionCustomColors
{
#ifdef NS_BUILD_REFCNT_LOGGING
SelectionCustomColors()
{
MOZ_COUNT_CTOR(SelectionCustomColors);
}
~SelectionCustomColors()
{
MOZ_COUNT_DTOR(SelectionCustomColors);
}
#endif
mozilla::Maybe<nscolor> mForegroundColor;
mozilla::Maybe<nscolor> mBackgroundColor;
mozilla::Maybe<nscolor> mAltForegroundColor;
mozilla::Maybe<nscolor> mAltBackgroundColor;
};
class nsIPresShell;
/** PeekOffsetStruct is used to group various arguments (both input and output)

Просмотреть файл

@ -3490,6 +3490,7 @@ Selection::Selection()
: mCachedOffsetForFrame(nullptr)
, mDirection(eDirNext)
, mSelectionType(SelectionType::eNormal)
, mCustomColors(nullptr)
, mUserInitiated(false)
, mCalledByJS(false)
, mSelectionChangeBlockerCount(0)
@ -3501,6 +3502,7 @@ Selection::Selection(nsFrameSelection* aList)
, mCachedOffsetForFrame(nullptr)
, mDirection(eDirNext)
, mSelectionType(SelectionType::eNormal)
, mCustomColors(nullptr)
, mUserInitiated(false)
, mCalledByJS(false)
, mSelectionChangeBlockerCount(0)
@ -6821,6 +6823,102 @@ Selection::SelectionLanguageChange(bool aLangRTL)
return NS_OK;
}
NS_IMETHODIMP
Selection::SetColors(const nsAString& aForegroundColor,
const nsAString& aBackgroundColor,
const nsAString& aAltForegroundColor,
const nsAString& aAltBackgroundColor)
{
ErrorResult result;
SetColors(aForegroundColor, aBackgroundColor,
aAltForegroundColor, aAltBackgroundColor, result);
return result.StealNSResult();
}
void
Selection::SetColors(const nsAString& aForegroundColor,
const nsAString& aBackgroundColor,
const nsAString& aAltForegroundColor,
const nsAString& aAltBackgroundColor,
ErrorResult& aRv)
{
if (mSelectionType != SelectionType::eFind) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
mCustomColors.reset(new SelectionCustomColors);
NS_NAMED_LITERAL_STRING(currentColorStr, "currentColor");
NS_NAMED_LITERAL_STRING(transparentStr, "transparent");
if (!aForegroundColor.Equals(currentColorStr)) {
nscolor foregroundColor;
nsAttrValue aForegroundColorValue;
aForegroundColorValue.ParseColor(aForegroundColor);
if (!aForegroundColorValue.GetColorValue(foregroundColor)) {
aRv.Throw(NS_ERROR_INVALID_ARG);
return;
}
mCustomColors->mForegroundColor = Some(foregroundColor);
} else {
mCustomColors->mForegroundColor = Nothing();
}
if (!aBackgroundColor.Equals(transparentStr)) {
nscolor backgroundColor;
nsAttrValue aBackgroundColorValue;
aBackgroundColorValue.ParseColor(aBackgroundColor);
if (!aBackgroundColorValue.GetColorValue(backgroundColor)) {
aRv.Throw(NS_ERROR_INVALID_ARG);
return;
}
mCustomColors->mBackgroundColor = Some(backgroundColor);
} else {
mCustomColors->mBackgroundColor = Nothing();
}
if (!aAltForegroundColor.Equals(currentColorStr)) {
nscolor altForegroundColor;
nsAttrValue aAltForegroundColorValue;
aAltForegroundColorValue.ParseColor(aAltForegroundColor);
if (!aAltForegroundColorValue.GetColorValue(altForegroundColor)) {
aRv.Throw(NS_ERROR_INVALID_ARG);
return;
}
mCustomColors->mAltForegroundColor = Some(altForegroundColor);
} else {
mCustomColors->mAltForegroundColor = Nothing();
}
if (!aAltBackgroundColor.Equals(transparentStr)) {
nscolor altBackgroundColor;
nsAttrValue aAltBackgroundColorValue;
aAltBackgroundColorValue.ParseColor(aAltBackgroundColor);
if (!aAltBackgroundColorValue.GetColorValue(altBackgroundColor)) {
aRv.Throw(NS_ERROR_INVALID_ARG);
return;
}
mCustomColors->mAltBackgroundColor = Some(altBackgroundColor);
} else {
mCustomColors->mAltBackgroundColor = Nothing();
}
}
NS_IMETHODIMP
Selection::ResetColors()
{
ErrorResult result;
ResetColors(result);
return result.StealNSResult();
}
void
Selection::ResetColors(ErrorResult& aRv)
{
mCustomColors = nullptr;
}
NS_IMETHODIMP_(nsDirection)
Selection::GetSelectionDirection() {
return mDirection;

Просмотреть файл

@ -3828,13 +3828,86 @@ nsTextPaintStyle::GetHighlightColors(nscolor* aForeColor,
NS_ASSERTION(aForeColor, "aForeColor is null");
NS_ASSERTION(aBackColor, "aBackColor is null");
nscolor backColor =
LookAndFeel::GetColor(LookAndFeel::eColorID_TextHighlightBackground);
nscolor foreColor =
LookAndFeel::GetColor(LookAndFeel::eColorID_TextHighlightForeground);
EnsureSufficientContrast(&foreColor, &backColor);
*aForeColor = foreColor;
*aBackColor = backColor;
const nsFrameSelection* frameSelection = mFrame->GetConstFrameSelection();
const Selection* selection =
frameSelection->GetSelection(SelectionType::eFind);
const SelectionCustomColors* customColors = nullptr;
if (selection) {
customColors = selection->GetCustomColors();
}
if (!customColors) {
nscolor backColor =
LookAndFeel::GetColor(LookAndFeel::eColorID_TextHighlightBackground);
nscolor foreColor =
LookAndFeel::GetColor(LookAndFeel::eColorID_TextHighlightForeground);
EnsureSufficientContrast(&foreColor, &backColor);
*aForeColor = foreColor;
*aBackColor = backColor;
return;
}
if (customColors->mForegroundColor && customColors->mBackgroundColor) {
nscolor foreColor = *customColors->mForegroundColor;
nscolor backColor = *customColors->mBackgroundColor;
if (EnsureSufficientContrast(&foreColor, &backColor) &&
customColors->mAltForegroundColor &&
customColors->mAltBackgroundColor) {
foreColor = *customColors->mAltForegroundColor;
backColor = *customColors->mAltBackgroundColor;
}
*aForeColor = foreColor;
*aBackColor = backColor;
return;
}
if (customColors->mBackgroundColor) {
// !mForegroundColor means "currentColor"; the current color of the text.
nscolor foreColor = GetTextColor();
nscolor backColor = *customColors->mBackgroundColor;
if (customColors->mAltBackgroundColor) {
int32_t foreLuminosityDifference =
NS_LUMINOSITY_DIFFERENCE(foreColor, backColor);
// The sufficient luminosity difference is based on the link color of
// about:preferences, so we don't invert the background color on these text.
// XXX: Make this more generic.
int32_t sufficientLuminosityDifference =
NS_LUMINOSITY_DIFFERENCE(NS_RGBA(23, 140, 229, 255), backColor);
if (foreLuminosityDifference < sufficientLuminosityDifference) {
backColor = *customColors->mAltBackgroundColor;
}
}
*aForeColor = foreColor;
*aBackColor = backColor;
return;
}
if (customColors->mForegroundColor) {
nscolor foreColor = *customColors->mForegroundColor;
// !mBackgroundColor means "transparent"; the current color of the background.
nscolor backColor = mFrameBackgroundColor;
if (customColors->mAltForegroundColor &&
EnsureSufficientContrast(&foreColor, &backColor)) {
foreColor = *customColors->mAltForegroundColor;
backColor = mFrameBackgroundColor;
}
*aForeColor = foreColor;
*aBackColor = backColor;
return;
}
// There are neither mForegroundColor nor mBackgroundColor.
*aForeColor = GetTextColor();
*aBackColor = NS_TRANSPARENT;
}
void

Просмотреть файл

@ -11,6 +11,7 @@
#include "mozilla/gfx/2D.h"
#include "mozilla/UniquePtr.h"
#include "nsFrame.h"
#include "nsFrameSelection.h"
#include "nsSplittableFrame.h"
#include "nsLineBox.h"
#include "gfxSkipChars.h"