Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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/. */
6 #include <gtk/gtk.h>
8 #include "nsColor.h"
9 #include "nsColorPicker.h"
10 #include "nsGtkUtils.h"
11 #include "nsIWidget.h"
12 #include "WidgetUtils.h"
14 NS_IMPL_ISUPPORTS(nsColorPicker, nsIColorPicker)
16 int nsColorPicker::convertGdkColorComponent(guint16 color_component) {
17 // GdkColor value is in range [0..65535]. We need something in range [0..255]
18 return (color_component * 255 + 127) / 65535;
19 }
21 guint16 nsColorPicker::convertToGdkColorComponent(int color_component) {
22 return color_component * 65535 / 255;
23 }
25 GdkColor nsColorPicker::convertToGdkColor(nscolor color) {
26 GdkColor result = { 0 /* obsolete, unused 'pixel' value */,
27 convertToGdkColorComponent(NS_GET_R(color)),
28 convertToGdkColorComponent(NS_GET_G(color)),
29 convertToGdkColorComponent(NS_GET_B(color)) };
31 return result;
32 }
34 GtkColorSelection* nsColorPicker::WidgetGetColorSelection(GtkWidget* widget)
35 {
36 return GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(
37 GTK_COLOR_SELECTION_DIALOG(widget)));
38 }
40 /* void init (in nsIDOMWindow parent, in AString title, in short mode); */
41 NS_IMETHODIMP nsColorPicker::Init(nsIDOMWindow *parent,
42 const nsAString& title,
43 const nsAString& initialColor)
44 {
45 mParentWidget = mozilla::widget::WidgetUtils::DOMWindowToWidget(parent);
46 mTitle = title;
47 mInitialColor = initialColor;
49 return NS_OK;
50 }
52 /* void open (in nsIColorPickerShownCallback aColorPickerShownCallback); */
53 NS_IMETHODIMP nsColorPicker::Open(nsIColorPickerShownCallback *aColorPickerShownCallback)
54 {
56 // Input color string should be 7 length (i.e. a string representing a valid
57 // simple color)
58 if (mInitialColor.Length() != 7) {
59 return NS_ERROR_FAILURE;
60 }
62 const nsAString& withoutHash = StringTail(mInitialColor, 6);
63 nscolor color;
64 if (!NS_HexToRGB(withoutHash, &color)) {
65 return NS_ERROR_FAILURE;
66 }
68 GdkColor color_gdk = convertToGdkColor(color);
70 if (mCallback) {
71 // It means Open has already been called: this is not allowed
72 NS_WARNING("mCallback is already set. Open called twice?");
73 return NS_ERROR_FAILURE;
74 }
75 mCallback = aColorPickerShownCallback;
77 nsXPIDLCString title;
78 title.Adopt(ToNewUTF8String(mTitle));
79 GtkWidget *color_chooser = gtk_color_selection_dialog_new(title);
81 GtkWindow *parent_window = GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET));
82 if (parent_window) {
83 GtkWindow *window = GTK_WINDOW(color_chooser);
84 gtk_window_set_transient_for(window, parent_window);
85 gtk_window_set_destroy_with_parent(window, TRUE);
86 }
88 gtk_color_selection_set_current_color(WidgetGetColorSelection(color_chooser),
89 &color_gdk);
91 NS_ADDREF_THIS();
92 g_signal_connect(WidgetGetColorSelection(color_chooser), "color-changed",
93 G_CALLBACK(OnColorChanged), this);
94 g_signal_connect(color_chooser, "response", G_CALLBACK(OnResponse), this);
95 g_signal_connect(color_chooser, "destroy", G_CALLBACK(OnDestroy), this);
96 gtk_widget_show(color_chooser);
98 return NS_OK;
99 }
101 /* static */ void
102 nsColorPicker::OnColorChanged(GtkColorSelection* colorselection,
103 gpointer user_data)
104 {
105 static_cast<nsColorPicker*>(user_data)->Update(colorselection);
106 }
108 /* static */ void
109 nsColorPicker::OnResponse(GtkWidget* color_chooser, gint response_id,
110 gpointer user_data)
111 {
112 static_cast<nsColorPicker*>(user_data)->
113 Done(color_chooser, response_id);
114 }
116 /* static */ void
117 nsColorPicker::OnDestroy(GtkWidget* color_chooser, gpointer user_data)
118 {
119 static_cast<nsColorPicker*>(user_data)->
120 Done(color_chooser, GTK_RESPONSE_CANCEL);
121 }
123 void
124 nsColorPicker::Update(GtkColorSelection* colorselection)
125 {
126 ReadValueFromColorSelection(colorselection);
127 if (mCallback) {
128 mCallback->Update(mColor);
129 }
130 }
132 void
133 nsColorPicker::Done(GtkWidget* color_chooser, gint response)
134 {
135 switch (response) {
136 case GTK_RESPONSE_OK:
137 case GTK_RESPONSE_ACCEPT:
138 ReadValueFromColorSelection(WidgetGetColorSelection(color_chooser));
139 break;
140 case GTK_RESPONSE_CANCEL:
141 case GTK_RESPONSE_CLOSE:
142 case GTK_RESPONSE_DELETE_EVENT:
143 mColor = mInitialColor;
144 break;
145 default:
146 NS_WARNING("Unexpected response");
147 break;
148 }
150 // A "response" signal won't be sent again but "destroy" will be.
151 g_signal_handlers_disconnect_by_func(color_chooser,
152 FuncToGpointer(OnDestroy), this);
154 gtk_widget_destroy(color_chooser);
155 if (mCallback) {
156 mCallback->Done(mColor);
157 mCallback = nullptr;
158 }
160 NS_RELEASE_THIS();
161 }
163 nsString nsColorPicker::ToHexString(int n)
164 {
165 nsString result;
166 if (n <= 0x0F) {
167 result.Append('0');
168 }
169 result.AppendInt(n, 16);
170 return result;
171 }
173 void nsColorPicker::ReadValueFromColorSelection(GtkColorSelection* colorselection)
174 {
175 GdkColor rgba;
176 gtk_color_selection_get_current_color(colorselection, &rgba);
178 mColor.AssignLiteral("#");
179 mColor += ToHexString(convertGdkColorComponent(rgba.red));
180 mColor += ToHexString(convertGdkColorComponent(rgba.green));
181 mColor += ToHexString(convertGdkColorComponent(rgba.blue));
182 }