widget/windows/nsColorPicker.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2  *
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "nsColorPicker.h"
     9 #include <shlwapi.h>
    11 #include "mozilla/AutoRestore.h"
    12 #include "nsIWidget.h"
    13 #include "WidgetUtils.h"
    15 using namespace mozilla::widget;
    17 namespace
    18 {
    19 // Manages NS_NATIVE_TMP_WINDOW child windows. NS_NATIVE_TMP_WINDOWs are
    20 // temporary child windows of mParentWidget created to address RTL issues
    21 // in picker dialogs. We are responsible for destroying these.
    22 class AutoDestroyTmpWindow
    23 {
    24 public:
    25   explicit AutoDestroyTmpWindow(HWND aTmpWnd) :
    26     mWnd(aTmpWnd) {
    27   }
    29   ~AutoDestroyTmpWindow() {
    30     if (mWnd)
    31       DestroyWindow(mWnd);
    32   }
    34   inline HWND get() const { return mWnd; }
    35 private:
    36   HWND mWnd;
    37 };
    39 static DWORD ColorStringToRGB(const nsAString& aColor)
    40 {
    41   DWORD result = 0;
    43   for (uint32_t i = 1; i < aColor.Length(); ++i) {
    44     result *= 16;
    46     char16_t c = aColor[i];
    47     if (c >= '0' && c <= '9') {
    48       result += c - '0';
    49     } else if (c >= 'a' && c <= 'f') {
    50       result += 10 + (c - 'a');
    51     } else {
    52       result += 10 + (c - 'A');
    53     }
    54   }
    56   DWORD r = result & 0x00FF0000;
    57   DWORD g = result & 0x0000FF00;
    58   DWORD b = result & 0x000000FF;
    60   r = r >> 16;
    61   b = b << 16;
    63   result = r | g | b;
    65   return result;
    66 }
    68 static nsString ToHexString(BYTE n)
    69 {
    70   nsString result;
    71   if (n <= 0x0F) {
    72     result.Append('0');
    73   }
    74   result.AppendInt(n, 16);
    75   return result;
    76 }
    79 static void
    80 BGRIntToRGBString(DWORD color, nsAString& aResult)
    81 {
    82   BYTE r = GetRValue(color);
    83   BYTE g = GetGValue(color);
    84   BYTE b = GetBValue(color);
    86   aResult.AssignLiteral("#");
    87   aResult.Append(ToHexString(r));
    88   aResult.Append(ToHexString(g));
    89   aResult.Append(ToHexString(b));
    90 }
    91 } // anonymous namespace
    93 AsyncColorChooser::AsyncColorChooser(const nsAString& aInitialColor,
    94                                      nsIWidget* aParentWidget,
    95                                      nsIColorPickerShownCallback* aCallback)
    96   : mInitialColor(aInitialColor)
    97   , mParentWidget(aParentWidget)
    98   , mCallback(aCallback)
    99 {
   100 }
   102 NS_IMETHODIMP
   103 AsyncColorChooser::Run()
   104 {
   105   static COLORREF sCustomColors[16] = {0} ;
   107   MOZ_ASSERT(NS_IsMainThread(),
   108       "Color pickers can only be opened from main thread currently");
   110   static bool sColorPickerOpen = false;
   111   // Allow only one color picker to be opened at a time, to workaround bug 944737
   112   if (!sColorPickerOpen) {
   113     mozilla::AutoRestore<bool> autoRestoreColorPickerOpen(sColorPickerOpen);
   114     sColorPickerOpen = true;
   116     AutoDestroyTmpWindow adtw((HWND) (mParentWidget.get() ?
   117       mParentWidget->GetNativeData(NS_NATIVE_TMP_WINDOW) : nullptr));
   119     CHOOSECOLOR options;
   120     options.lStructSize   = sizeof(options);
   121     options.hwndOwner     = adtw.get();
   122     options.Flags         = CC_RGBINIT | CC_FULLOPEN;
   123     options.rgbResult     = ColorStringToRGB(mInitialColor);
   124     options.lpCustColors  = sCustomColors;
   126     if (ChooseColor(&options)) {
   127       BGRIntToRGBString(options.rgbResult, mColor);
   128     }
   129   } else {
   130     NS_WARNING("Currently, it's not possible to open more than one color "
   131                "picker at a time");
   132     mColor = mInitialColor;
   133   }
   135   if (mCallback) {
   136     mCallback->Done(mColor);
   137   }
   139   return NS_OK;
   140 }
   142 ///////////////////////////////////////////////////////////////////////////////
   143 // nsIColorPicker
   145 nsColorPicker::nsColorPicker()
   146 {
   147 }
   149 nsColorPicker::~nsColorPicker()
   150 {
   151 }
   153 NS_IMPL_ISUPPORTS(nsColorPicker, nsIColorPicker)
   155 NS_IMETHODIMP
   156 nsColorPicker::Init(nsIDOMWindow* parent,
   157                     const nsAString& title,
   158                     const nsAString& aInitialColor)
   159 {
   160   NS_PRECONDITION(parent,
   161       "Null parent passed to colorpicker, no color picker for you!");
   162   mParentWidget =  WidgetUtils::DOMWindowToWidget(parent);
   163   mInitialColor = aInitialColor;
   164   return NS_OK;
   165 }
   167 NS_IMETHODIMP
   168 nsColorPicker::Open(nsIColorPickerShownCallback* aCallback)
   169 {
   170   NS_ENSURE_ARG(aCallback);
   171   nsCOMPtr<nsIRunnable> event = new AsyncColorChooser(mInitialColor, mParentWidget, aCallback);
   172   return NS_DispatchToMainThread(event);
   173 }

mercurial