forked from mirrors/gecko-dev
		
	 0d74f2d95f
			
		
	
	
		0d74f2d95f
		
	
	
	
	
		
			
			Cleans up the code a bit to make actually used fallback code easier to spot and update the required GTK version so deprecation warnings are more accurate. Also make `gdk_window_set_opaque_region` always available - we can now assume it to be present in all supported versions. Differential Revision: https://phabricator.services.mozilla.com/D82804
		
			
				
	
	
		
			242 lines
		
	
	
	
		
			7.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			242 lines
		
	
	
	
		
			7.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- 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 <gtk/gtk.h>
 | |
| 
 | |
| #include "nsColor.h"
 | |
| #include "nsColorPicker.h"
 | |
| #include "nsGtkUtils.h"
 | |
| #include "nsIWidget.h"
 | |
| #include "WidgetUtils.h"
 | |
| #include "nsPIDOMWindow.h"
 | |
| 
 | |
| NS_IMPL_ISUPPORTS(nsColorPicker, nsIColorPicker)
 | |
| 
 | |
| #if defined(ACTIVATE_GTK3_COLOR_PICKER)
 | |
| int nsColorPicker::convertGdkRgbaComponent(gdouble color_component) {
 | |
|   // GdkRGBA value is in range [0.0..1.0]. We need something in range [0..255]
 | |
|   return color_component * 255 + 0.5;
 | |
| }
 | |
| 
 | |
| gdouble nsColorPicker::convertToGdkRgbaComponent(int color_component) {
 | |
|   return color_component / 255.0;
 | |
| }
 | |
| 
 | |
| GdkRGBA nsColorPicker::convertToRgbaColor(nscolor color) {
 | |
|   GdkRGBA result = {convertToGdkRgbaComponent(NS_GET_R(color)),
 | |
|                     convertToGdkRgbaComponent(NS_GET_G(color)),
 | |
|                     convertToGdkRgbaComponent(NS_GET_B(color)),
 | |
|                     convertToGdkRgbaComponent(NS_GET_A(color))};
 | |
| 
 | |
|   return result;
 | |
| }
 | |
| #else
 | |
| int nsColorPicker::convertGdkColorComponent(guint16 color_component) {
 | |
|   // GdkColor value is in range [0..65535]. We need something in range [0..255]
 | |
|   return (color_component * 255 + 127) / 65535;
 | |
| }
 | |
| 
 | |
| guint16 nsColorPicker::convertToGdkColorComponent(int color_component) {
 | |
|   return color_component * 65535 / 255;
 | |
| }
 | |
| 
 | |
| GdkColor nsColorPicker::convertToGdkColor(nscolor color) {
 | |
|   GdkColor result = {0 /* obsolete, unused 'pixel' value */,
 | |
|                      convertToGdkColorComponent(NS_GET_R(color)),
 | |
|                      convertToGdkColorComponent(NS_GET_G(color)),
 | |
|                      convertToGdkColorComponent(NS_GET_B(color))};
 | |
| 
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| GtkColorSelection* nsColorPicker::WidgetGetColorSelection(GtkWidget* widget) {
 | |
|   return GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(
 | |
|       GTK_COLOR_SELECTION_DIALOG(widget)));
 | |
| }
 | |
| #endif
 | |
| 
 | |
| NS_IMETHODIMP nsColorPicker::Init(mozIDOMWindowProxy* aParent,
 | |
|                                   const nsAString& title,
 | |
|                                   const nsAString& initialColor) {
 | |
|   auto* parent = nsPIDOMWindowOuter::From(aParent);
 | |
|   mParentWidget = mozilla::widget::WidgetUtils::DOMWindowToWidget(parent);
 | |
|   mTitle = title;
 | |
|   mInitialColor = initialColor;
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP nsColorPicker::Open(
 | |
|     nsIColorPickerShownCallback* aColorPickerShownCallback) {
 | |
|   // Input color string should be 7 length (i.e. a string representing a valid
 | |
|   // simple color)
 | |
|   if (mInitialColor.Length() != 7) {
 | |
|     return NS_ERROR_FAILURE;
 | |
|   }
 | |
| 
 | |
|   const nsAString& withoutHash = StringTail(mInitialColor, 6);
 | |
|   nscolor color;
 | |
|   if (!NS_HexToRGBA(withoutHash, nsHexColorType::NoAlpha, &color)) {
 | |
|     return NS_ERROR_FAILURE;
 | |
|   }
 | |
| 
 | |
|   if (mCallback) {
 | |
|     // It means Open has already been called: this is not allowed
 | |
|     NS_WARNING("mCallback is already set. Open called twice?");
 | |
|     return NS_ERROR_FAILURE;
 | |
|   }
 | |
|   mCallback = aColorPickerShownCallback;
 | |
| 
 | |
|   NS_ConvertUTF16toUTF8 title(mTitle);
 | |
|   GtkWindow* parent_window =
 | |
|       GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET));
 | |
| 
 | |
| #if defined(ACTIVATE_GTK3_COLOR_PICKER)
 | |
|   GtkWidget* color_chooser = gtk_color_chooser_dialog_new(title, parent_window);
 | |
| 
 | |
|   if (parent_window) {
 | |
|     GtkWindow* window = GTK_WINDOW(color_chooser);
 | |
|     gtk_window_set_destroy_with_parent(window, TRUE);
 | |
|     if (gtk_window_get_modal(parent_window)) {
 | |
|       gtk_window_set_modal(window, TRUE);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(color_chooser), FALSE);
 | |
|   GdkRGBA color_rgba = convertToRgbaColor(color);
 | |
|   gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(color_chooser), &color_rgba);
 | |
| 
 | |
|   g_signal_connect(GTK_COLOR_CHOOSER(color_chooser), "color-activated",
 | |
|                    G_CALLBACK(OnColorChanged), this);
 | |
| #else
 | |
|   GtkWidget* color_chooser = gtk_color_selection_dialog_new(title.get());
 | |
| 
 | |
|   if (parent_window) {
 | |
|     GtkWindow* window = GTK_WINDOW(color_chooser);
 | |
|     gtk_window_set_transient_for(window, parent_window);
 | |
|     gtk_window_set_destroy_with_parent(window, TRUE);
 | |
|     if (gtk_window_get_modal(parent_window)) {
 | |
|       gtk_window_set_modal(window, TRUE);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   GdkColor color_gdk = convertToGdkColor(color);
 | |
|   gtk_color_selection_set_current_color(WidgetGetColorSelection(color_chooser),
 | |
|                                         &color_gdk);
 | |
| 
 | |
|   g_signal_connect(WidgetGetColorSelection(color_chooser), "color-changed",
 | |
|                    G_CALLBACK(OnColorChanged), this);
 | |
| #endif
 | |
| 
 | |
|   NS_ADDREF_THIS();
 | |
| 
 | |
|   g_signal_connect(color_chooser, "response", G_CALLBACK(OnResponse), this);
 | |
|   g_signal_connect(color_chooser, "destroy", G_CALLBACK(OnDestroy), this);
 | |
|   gtk_widget_show(color_chooser);
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| #if defined(ACTIVATE_GTK3_COLOR_PICKER)
 | |
| /* static */
 | |
| void nsColorPicker::OnColorChanged(GtkColorChooser* color_chooser,
 | |
|                                    GdkRGBA* color, gpointer user_data) {
 | |
|   static_cast<nsColorPicker*>(user_data)->Update(color);
 | |
| }
 | |
| 
 | |
| void nsColorPicker::Update(GdkRGBA* color) {
 | |
|   SetColor(color);
 | |
|   if (mCallback) {
 | |
|     mCallback->Update(mColor);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void nsColorPicker::SetColor(const GdkRGBA* color) {
 | |
|   mColor.Assign('#');
 | |
|   mColor += ToHexString(convertGdkRgbaComponent(color->red));
 | |
|   mColor += ToHexString(convertGdkRgbaComponent(color->green));
 | |
|   mColor += ToHexString(convertGdkRgbaComponent(color->blue));
 | |
| }
 | |
| #else
 | |
| /* static */
 | |
| void nsColorPicker::OnColorChanged(GtkColorSelection* colorselection,
 | |
|                                    gpointer user_data) {
 | |
|   static_cast<nsColorPicker*>(user_data)->Update(colorselection);
 | |
| }
 | |
| 
 | |
| void nsColorPicker::Update(GtkColorSelection* colorselection) {
 | |
|   ReadValueFromColorSelection(colorselection);
 | |
|   if (mCallback) {
 | |
|     mCallback->Update(mColor);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void nsColorPicker::ReadValueFromColorSelection(
 | |
|     GtkColorSelection* colorselection) {
 | |
|   GdkColor rgba;
 | |
|   gtk_color_selection_get_current_color(colorselection, &rgba);
 | |
| 
 | |
|   mColor.Assign('#');
 | |
|   mColor += ToHexString(convertGdkColorComponent(rgba.red));
 | |
|   mColor += ToHexString(convertGdkColorComponent(rgba.green));
 | |
|   mColor += ToHexString(convertGdkColorComponent(rgba.blue));
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /* static */
 | |
| void nsColorPicker::OnResponse(GtkWidget* color_chooser, gint response_id,
 | |
|                                gpointer user_data) {
 | |
|   static_cast<nsColorPicker*>(user_data)->Done(color_chooser, response_id);
 | |
| }
 | |
| 
 | |
| /* static */
 | |
| void nsColorPicker::OnDestroy(GtkWidget* color_chooser, gpointer user_data) {
 | |
|   static_cast<nsColorPicker*>(user_data)->Done(color_chooser,
 | |
|                                                GTK_RESPONSE_CANCEL);
 | |
| }
 | |
| 
 | |
| void nsColorPicker::Done(GtkWidget* color_chooser, gint response) {
 | |
|   switch (response) {
 | |
|     case GTK_RESPONSE_OK:
 | |
|     case GTK_RESPONSE_ACCEPT:
 | |
| #if defined(ACTIVATE_GTK3_COLOR_PICKER)
 | |
|       GdkRGBA color;
 | |
|       gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(color_chooser), &color);
 | |
|       SetColor(&color);
 | |
| #else
 | |
|       ReadValueFromColorSelection(WidgetGetColorSelection(color_chooser));
 | |
| #endif
 | |
|       break;
 | |
|     case GTK_RESPONSE_CANCEL:
 | |
|     case GTK_RESPONSE_CLOSE:
 | |
|     case GTK_RESPONSE_DELETE_EVENT:
 | |
|       mColor = mInitialColor;
 | |
|       break;
 | |
|     default:
 | |
|       NS_WARNING("Unexpected response");
 | |
|       break;
 | |
|   }
 | |
| 
 | |
|   // A "response" signal won't be sent again but "destroy" will be.
 | |
|   g_signal_handlers_disconnect_by_func(color_chooser, FuncToGpointer(OnDestroy),
 | |
|                                        this);
 | |
| 
 | |
|   gtk_widget_destroy(color_chooser);
 | |
|   if (mCallback) {
 | |
|     mCallback->Done(mColor);
 | |
|     mCallback = nullptr;
 | |
|   }
 | |
| 
 | |
|   NS_RELEASE_THIS();
 | |
| }
 | |
| 
 | |
| nsString nsColorPicker::ToHexString(int n) {
 | |
|   nsString result;
 | |
|   if (n <= 0x0F) {
 | |
|     result.Append('0');
 | |
|   }
 | |
|   result.AppendInt(n, 16);
 | |
|   return result;
 | |
| }
 |