Bug 875754 - Implement <input type="color">: Windows widget/color picker. r=jimm

This commit is contained in:
Arnaud Bienner 2013-06-23 18:48:24 +02:00
parent 69084ace53
commit 63fda59c53
4 changed files with 235 additions and 0 deletions

View File

@ -41,6 +41,7 @@ CPP_SOURCES += [
'nsAppShell.cpp',
'nsBidiKeyboard.cpp',
'nsClipboard.cpp',
'nsColorPicker.cpp',
'nsDataObj.cpp',
'nsDataObjCollection.cpp',
'nsDragService.cpp',

View File

@ -0,0 +1,154 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsColorPicker.h"
#include <shlwapi.h>
#include "nsIWidget.h"
#include "WidgetUtils.h"
using namespace mozilla::widget;
namespace
{
// Manages NS_NATIVE_TMP_WINDOW child windows. NS_NATIVE_TMP_WINDOWs are
// temporary child windows of mParentWidget created to address RTL issues
// in picker dialogs. We are responsible for destroying these.
class AutoDestroyTmpWindow
{
public:
explicit AutoDestroyTmpWindow(HWND aTmpWnd) :
mWnd(aTmpWnd) {
}
~AutoDestroyTmpWindow() {
if (mWnd)
DestroyWindow(mWnd);
}
inline HWND get() const { return mWnd; }
private:
HWND mWnd;
};
static DWORD ColorStringToRGB(const nsAString& aColor)
{
DWORD result = 0;
for (uint32_t i = 1; i < aColor.Length(); ++i) {
result *= 16;
PRUnichar c = aColor[i];
if (c >= '0' && c <= '9') {
result += c - '0';
} else if (c >= 'a' && c <= 'f') {
result += 10 + (c - 'a');
} else {
result += 10 + (c - 'A');
}
}
DWORD r = result & 0x00FF0000;
DWORD g = result & 0x0000FF00;
DWORD b = result & 0x000000FF;
r = r >> 16;
b = b << 16;
result = r | g | b;
return result;
}
static nsString ToHexString(BYTE n)
{
nsString result;
if (n <= 0x0F) {
result.Append('0');
}
result.AppendInt(n, 16);
return result;
}
static void
BGRIntToRGBString(DWORD color, nsAString& aResult)
{
BYTE r = GetRValue(color);
BYTE g = GetGValue(color);
BYTE b = GetBValue(color);
aResult.AssignLiteral("#");
aResult.Append(ToHexString(r));
aResult.Append(ToHexString(g));
aResult.Append(ToHexString(b));
}
} // anonymous namespace
AsyncColorChooser::AsyncColorChooser(DWORD aInitialColor, nsIWidget* aParentWidget, nsIColorPickerShownCallback* aCallback)
: mInitialColor(aInitialColor)
, mParentWidget(aParentWidget)
, mCallback(aCallback)
{
}
NS_IMETHODIMP
AsyncColorChooser::Run()
{
CHOOSECOLOR options;
static COLORREF customColors[16] = {0} ;
AutoDestroyTmpWindow adtw((HWND) (mParentWidget.get() ?
mParentWidget->GetNativeData(NS_NATIVE_TMP_WINDOW) : NULL));
options.lStructSize = sizeof(options);
options.hwndOwner = adtw.get();
options.Flags = CC_RGBINIT | CC_FULLOPEN;
options.rgbResult = mInitialColor;
options.lpCustColors = customColors;
if (ChooseColor(&options)) {
BGRIntToRGBString(options.rgbResult, mColor);
}
if (mCallback) {
mCallback->Done(mColor);
}
return NS_OK;
}
///////////////////////////////////////////////////////////////////////////////
// nsIColorPicker
nsColorPicker::nsColorPicker()
{
}
nsColorPicker::~nsColorPicker()
{
}
NS_IMPL_ISUPPORTS1(nsColorPicker, nsIColorPicker)
NS_IMETHODIMP
nsColorPicker::Init(nsIDOMWindow* parent, const nsAString& title, const nsAString& aInitialColor)
{
NS_PRECONDITION(parent,
"Null parent passed to colorpicker, no color picker for you!");
mParentWidget = WidgetUtils::DOMWindowToWidget(parent);
mInitialColor = ColorStringToRGB(aInitialColor);
return NS_OK;
}
NS_IMETHODIMP
nsColorPicker::Open(nsIColorPickerShownCallback* aCallback)
{
NS_ENSURE_ARG(aCallback);
nsCOMPtr<nsIRunnable> event = new AsyncColorChooser(mInitialColor, mParentWidget, aCallback);
return NS_DispatchToMainThread(event);
}

View File

@ -0,0 +1,51 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsColorPicker_h__
#define nsColorPicker_h__
#include <windows.h>
#include <commdlg.h>
#include "nsCOMPtr.h"
#include "nsIColorPicker.h"
#include "nsString.h"
#include "nsThreadUtils.h"
class nsIWidget;
class AsyncColorChooser :
public nsRunnable
{
public:
AsyncColorChooser(DWORD aInitialColor, nsIWidget* aParentWidget, nsIColorPickerShownCallback* aCallback);
NS_IMETHOD Run() MOZ_OVERRIDE;
private:
DWORD mInitialColor;
nsCOMPtr<nsIWidget> mParentWidget;
nsCOMPtr<nsIColorPickerShownCallback> mCallback;
nsString mColor;
};
class nsColorPicker :
public nsIColorPicker
{
public:
nsColorPicker();
virtual ~nsColorPicker();
NS_DECL_ISUPPORTS
NS_IMETHOD Init(nsIDOMWindow* parent, const nsAString& title, const nsAString& aInitialColor);
NS_IMETHOD Open(nsIColorPickerShownCallback* aCallback);
protected:
DWORD mInitialColor;
nsCOMPtr<nsIWidget> mParentWidget;
};
#endif // nsColorPicker_h__

View File

@ -25,6 +25,7 @@
#include "nsXULAppAPI.h"
// Desktop
#include "nsFilePicker.h" // needs to be included before other shobjidl.h includes
#include "nsColorPicker.h"
#include "nsNativeThemeWin.h"
#include "nsWindow.h"
// Content processes
@ -125,6 +126,31 @@ FilePickerConstructor(nsISupports *aOuter, REFNSIID aIID,
return picker->QueryInterface(aIID, aResult);
}
static nsresult
ColorPickerConstructor(nsISupports *aOuter, REFNSIID aIID,
void **aResult)
{
*aResult = nullptr;
if (aOuter != nullptr) {
return NS_ERROR_NO_AGGREGATION;
}
nsCOMPtr<nsIColorPicker> picker;
if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro) {
#ifdef MOZ_METRO
// TODO
// picker = new nsMetroColorPicker;
NS_ERROR("metro color picker isn't implemented currently");
return NS_ERROR_NO_INTERFACE;
#else
NS_RUNTIMEABORT("build does not support metro.");
#endif
} else {
picker = new nsColorPicker;
}
return picker->QueryInterface(aIID, aResult);
}
NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerWin)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIdleServiceWin, nsIdleServiceWin::GetInstance)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboard)
@ -160,6 +186,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(GfxInfo, Init)
NS_DEFINE_NAMED_CID(NS_WINDOW_CID);
NS_DEFINE_NAMED_CID(NS_CHILD_CID);
NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID);
NS_DEFINE_NAMED_CID(NS_COLORPICKER_CID);
NS_DEFINE_NAMED_CID(NS_APPSHELL_CID);
NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID);
NS_DEFINE_NAMED_CID(NS_GFXINFO_CID);
@ -193,6 +220,7 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
{ &kNS_WINDOW_CID, false, NULL, WindowConstructor },
{ &kNS_CHILD_CID, false, NULL, ChildWindowConstructor },
{ &kNS_FILEPICKER_CID, false, NULL, FilePickerConstructor },
{ &kNS_COLORPICKER_CID, false, NULL, ColorPickerConstructor },
{ &kNS_APPSHELL_CID, false, NULL, nsAppShellConstructor },
{ &kNS_SCREENMANAGER_CID, false, NULL, nsScreenManagerWinConstructor },
{ &kNS_GFXINFO_CID, false, NULL, GfxInfoConstructor },
@ -227,6 +255,7 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
{ "@mozilla.org/widgets/window/win;1", &kNS_WINDOW_CID },
{ "@mozilla.org/widgets/child_window/win;1", &kNS_CHILD_CID },
{ "@mozilla.org/filepicker;1", &kNS_FILEPICKER_CID },
{ "@mozilla.org/colorpicker;1", &kNS_COLORPICKER_CID },
{ "@mozilla.org/widget/appshell/win;1", &kNS_APPSHELL_CID },
{ "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID },
{ "@mozilla.org/gfx/info;1", &kNS_GFXINFO_CID },