1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
9 #include "nsColorPicker.h"
10 #include "nsGtkUtils.h"
11 #include "nsIWidget.h"
12 #include "WidgetUtils.h"
13 #include "nsPIDOMWindow.h"
15 NS_IMPL_ISUPPORTS(nsColorPicker
, nsIColorPicker
)
17 #if defined(ACTIVATE_GTK3_COLOR_PICKER)
18 int nsColorPicker::convertGdkRgbaComponent(gdouble color_component
) {
19 // GdkRGBA value is in range [0.0..1.0]. We need something in range [0..255]
20 return color_component
* 255 + 0.5;
23 gdouble
nsColorPicker::convertToGdkRgbaComponent(int color_component
) {
24 return color_component
/ 255.0;
27 GdkRGBA
nsColorPicker::convertToRgbaColor(nscolor color
) {
28 GdkRGBA result
= {convertToGdkRgbaComponent(NS_GET_R(color
)),
29 convertToGdkRgbaComponent(NS_GET_G(color
)),
30 convertToGdkRgbaComponent(NS_GET_B(color
)),
31 convertToGdkRgbaComponent(NS_GET_A(color
))};
36 int nsColorPicker::convertGdkColorComponent(guint16 color_component
) {
37 // GdkColor value is in range [0..65535]. We need something in range [0..255]
38 return (color_component
* 255 + 127) / 65535;
41 guint16
nsColorPicker::convertToGdkColorComponent(int color_component
) {
42 return color_component
* 65535 / 255;
45 GdkColor
nsColorPicker::convertToGdkColor(nscolor color
) {
46 GdkColor result
= {0 /* obsolete, unused 'pixel' value */,
47 convertToGdkColorComponent(NS_GET_R(color
)),
48 convertToGdkColorComponent(NS_GET_G(color
)),
49 convertToGdkColorComponent(NS_GET_B(color
))};
54 GtkColorSelection
* nsColorPicker::WidgetGetColorSelection(GtkWidget
* widget
) {
55 return GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(
56 GTK_COLOR_SELECTION_DIALOG(widget
)));
60 NS_IMETHODIMP
nsColorPicker::Init(mozIDOMWindowProxy
* aParent
,
61 const nsAString
& title
,
62 const nsAString
& initialColor
) {
63 auto* parent
= nsPIDOMWindowOuter::From(aParent
);
64 mParentWidget
= mozilla::widget::WidgetUtils::DOMWindowToWidget(parent
);
66 mInitialColor
= initialColor
;
71 NS_IMETHODIMP
nsColorPicker::Open(
72 nsIColorPickerShownCallback
* aColorPickerShownCallback
) {
73 // Input color string should be 7 length (i.e. a string representing a valid
75 if (mInitialColor
.Length() != 7) {
76 return NS_ERROR_FAILURE
;
79 const nsAString
& withoutHash
= StringTail(mInitialColor
, 6);
81 if (!NS_HexToRGBA(withoutHash
, nsHexColorType::NoAlpha
, &color
)) {
82 return NS_ERROR_FAILURE
;
86 // It means Open has already been called: this is not allowed
87 NS_WARNING("mCallback is already set. Open called twice?");
88 return NS_ERROR_FAILURE
;
90 mCallback
= aColorPickerShownCallback
;
92 NS_ConvertUTF16toUTF8
title(mTitle
);
93 GtkWindow
* parent_window
=
94 GTK_WINDOW(mParentWidget
->GetNativeData(NS_NATIVE_SHELLWIDGET
));
96 #if defined(ACTIVATE_GTK3_COLOR_PICKER)
97 GtkWidget
* color_chooser
=
98 gtk_color_chooser_dialog_new(title
.get(), parent_window
);
101 GtkWindow
* window
= GTK_WINDOW(color_chooser
);
102 gtk_window_set_destroy_with_parent(window
, TRUE
);
103 if (gtk_window_get_modal(parent_window
)) {
104 gtk_window_set_modal(window
, TRUE
);
108 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(color_chooser
), FALSE
);
109 GdkRGBA color_rgba
= convertToRgbaColor(color
);
110 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(color_chooser
), &color_rgba
);
112 g_signal_connect(GTK_COLOR_CHOOSER(color_chooser
), "color-activated",
113 G_CALLBACK(OnColorChanged
), this);
115 GtkWidget
* color_chooser
= gtk_color_selection_dialog_new(title
.get());
118 GtkWindow
* window
= GTK_WINDOW(color_chooser
);
119 gtk_window_set_transient_for(window
, parent_window
);
120 gtk_window_set_destroy_with_parent(window
, TRUE
);
121 if (gtk_window_get_modal(parent_window
)) {
122 gtk_window_set_modal(window
, TRUE
);
126 GdkColor color_gdk
= convertToGdkColor(color
);
127 gtk_color_selection_set_current_color(WidgetGetColorSelection(color_chooser
),
130 g_signal_connect(WidgetGetColorSelection(color_chooser
), "color-changed",
131 G_CALLBACK(OnColorChanged
), this);
136 g_signal_connect(color_chooser
, "response", G_CALLBACK(OnResponse
), this);
137 g_signal_connect(color_chooser
, "destroy", G_CALLBACK(OnDestroy
), this);
138 gtk_widget_show(color_chooser
);
143 #if defined(ACTIVATE_GTK3_COLOR_PICKER)
145 void nsColorPicker::OnColorChanged(GtkColorChooser
* color_chooser
,
146 GdkRGBA
* color
, gpointer user_data
) {
147 static_cast<nsColorPicker
*>(user_data
)->Update(color
);
150 void nsColorPicker::Update(GdkRGBA
* color
) {
153 mCallback
->Update(mColor
);
157 void nsColorPicker::SetColor(const GdkRGBA
* color
) {
159 mColor
+= ToHexString(convertGdkRgbaComponent(color
->red
));
160 mColor
+= ToHexString(convertGdkRgbaComponent(color
->green
));
161 mColor
+= ToHexString(convertGdkRgbaComponent(color
->blue
));
165 void nsColorPicker::OnColorChanged(GtkColorSelection
* colorselection
,
166 gpointer user_data
) {
167 static_cast<nsColorPicker
*>(user_data
)->Update(colorselection
);
170 void nsColorPicker::Update(GtkColorSelection
* colorselection
) {
171 ReadValueFromColorSelection(colorselection
);
173 mCallback
->Update(mColor
);
177 void nsColorPicker::ReadValueFromColorSelection(
178 GtkColorSelection
* colorselection
) {
180 gtk_color_selection_get_current_color(colorselection
, &rgba
);
183 mColor
+= ToHexString(convertGdkColorComponent(rgba
.red
));
184 mColor
+= ToHexString(convertGdkColorComponent(rgba
.green
));
185 mColor
+= ToHexString(convertGdkColorComponent(rgba
.blue
));
190 void nsColorPicker::OnResponse(GtkWidget
* color_chooser
, gint response_id
,
191 gpointer user_data
) {
192 static_cast<nsColorPicker
*>(user_data
)->Done(color_chooser
, response_id
);
196 void nsColorPicker::OnDestroy(GtkWidget
* color_chooser
, gpointer user_data
) {
197 static_cast<nsColorPicker
*>(user_data
)->Done(color_chooser
,
198 GTK_RESPONSE_CANCEL
);
201 void nsColorPicker::Done(GtkWidget
* color_chooser
, gint response
) {
203 case GTK_RESPONSE_OK
:
204 case GTK_RESPONSE_ACCEPT
:
205 #if defined(ACTIVATE_GTK3_COLOR_PICKER)
207 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(color_chooser
), &color
);
210 ReadValueFromColorSelection(WidgetGetColorSelection(color_chooser
));
213 case GTK_RESPONSE_CANCEL
:
214 case GTK_RESPONSE_CLOSE
:
215 case GTK_RESPONSE_DELETE_EVENT
:
216 mColor
= mInitialColor
;
219 NS_WARNING("Unexpected response");
223 // A "response" signal won't be sent again but "destroy" will be.
224 g_signal_handlers_disconnect_by_func(color_chooser
, FuncToGpointer(OnDestroy
),
227 gtk_widget_destroy(color_chooser
);
229 mCallback
->Done(mColor
);
236 nsString
nsColorPicker::ToHexString(int n
) {
241 result
.AppendInt(n
, 16);