Blob Blame History Raw
From daefb444e2757b0fda729cafbeea7c19efa979a3 Mon Sep 17 00:00:00 2001
From: Eric Williams
Date: Thu, 26 Nov 2015 08:46:27 -0500
Subject: Bug 479998: [GTK3] Form/wizard Composites have incorrect background
 colors

As of GTK3.16 gtk_widget_override_background_color() is deprecated.
Unfortunately in GTK3.18 it has started to break the background colors
of SwtFixed containers. This is most notably visible in the workspace
selection and commit dialogs, where some background containers had the
default gray background color when they should have been white.

This fix overrides the draw signal in Composite, which allows for CSS
rendering of the background color using gtk_render_background(), which
is the recommended fix as per the GTK team's changes. This ensures that
every composite is drawn with the correct background color if it is set. 

The only additional side effect is that ToolBar background colors need
to be set with CSS also, since some SwtFixed containers that were
previously being overridden by ToolBar background colors now are
correctly displaying their own background. This means that ToolBars need
to be rendered with CSS as well. This can be accomplished very easily by
overriding the setBackgroundColor() method in ToolBar.java.

This change will only affect SWT using GTK3.16 and upward. Anything
below 3.16 still uses the old function (which works reliably on those
versions).

Change-Id: If9d1037fd24b9739e0c30ff794eb6fed0247d56f
Signed-off-by: Eric Williams <ericwill@redhat.com>
---
 .../Eclipse SWT PI/gtk/library/os.c                | 26 +++++++++++++-
 .../Eclipse SWT PI/gtk/library/os.h                |  1 +
 .../Eclipse SWT PI/gtk/library/os_custom.h         |  1 +
 .../Eclipse SWT PI/gtk/library/os_stats.c          |  1 +
 .../Eclipse SWT PI/gtk/library/os_stats.h          |  1 +
 .../gtk/org/eclipse/swt/internal/gtk/OS.java       | 13 +++++++
 .../gtk/org/eclipse/swt/widgets/Composite.java     | 40 ++++++++++++++++++++++
 .../gtk/org/eclipse/swt/widgets/Control.java       | 29 ++++++++++++----
 .../gtk/org/eclipse/swt/widgets/ToolBar.java       | 10 ++++++
 9 files changed, 115 insertions(+), 7 deletions(-)

diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c
index 52ade78..2d47a1c 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c	
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c	
@@ -7181,6 +7181,30 @@ fail:
 }
 #endif
 
+#ifndef NO__1gdk_1rgba_1to_1string
+JNIEXPORT jintLong JNICALL OS_NATIVE(_1gdk_1rgba_1to_1string)
+	(JNIEnv *env, jclass that, jobject arg0)
+{
+	GdkRGBA _arg0, *lparg0=NULL;
+	jintLong rc = 0;
+	OS_NATIVE_ENTER(env, that, _1gdk_1rgba_1to_1string_FUNC);
+	if (arg0) if ((lparg0 = getGdkRGBAFields(env, arg0, &_arg0)) == NULL) goto fail;
+/*
+	rc = (jintLong)gdk_rgba_to_string((GdkRGBA *)lparg0);
+*/
+	{
+		OS_LOAD_FUNCTION(fp, gdk_rgba_to_string)
+		if (fp) {
+			rc = (jintLong)((jintLong (CALLING_CONVENTION*)(GdkRGBA *))fp)((GdkRGBA *)lparg0);
+		}
+	}
+fail:
+	if (arg0 && lparg0) setGdkRGBAFields(env, arg0, lparg0);
+	OS_NATIVE_EXIT(env, that, _1gdk_1rgba_1to_1string_FUNC);
+	return rc;
+}
+#endif
+
 #ifndef NO__1gdk_1screen_1get_1default
 JNIEXPORT jintLong JNICALL OS_NATIVE(_1gdk_1screen_1get_1default)
 	(JNIEnv *env, jclass that)
@@ -18352,7 +18376,7 @@ JNIEXPORT jint JNICALL OS_NATIVE(_1gtk_1widget_1get_1state_1flags)
 	{
 		OS_LOAD_FUNCTION(fp, gtk_widget_get_state_flags)
 		if (fp) {
-			rc = (jint)((jintLong (CALLING_CONVENTION*)(GtkWidget *))fp)((GtkWidget *)arg0);
+			rc = (jint)((jint (CALLING_CONVENTION*)(GtkWidget *))fp)((GtkWidget *)arg0);
 		}
 	}
 	OS_NATIVE_EXIT(env, that, _1gtk_1widget_1get_1state_1flags_FUNC);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.h
index 2ccdca2..90084ea 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.h	
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.h	
@@ -184,6 +184,7 @@
 #define NO__1gtk_1style_1context_1set_1state
 #define NO__1gtk_1color_1chooser_1get_1rgba
 #define NO__1gtk_1color_1chooser_1set_1rgba
+#define NO__1gdk_1rgba_1to_1string
 
 #define NO__1g_1object_1set__I_3BLorg_eclipse_swt_internal_gtk_GdkRGBA_2I
 #define NO__1g_1object_1set__J_3BLorg_eclipse_swt_internal_gtk_GdkRGBA_2J
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h
index a293df9..6cd4c80 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h	
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h	
@@ -307,6 +307,7 @@
 #define gdk_pointer_ungrab_LIB LIB_GDK
 #define gdk_region_polygon_LIB LIB_GDK
 #define gdk_region_get_rectangles_LIB LIB_GDK
+#define gdk_rgba_to_string_LIB LIB_GDK
 #define gdk_screen_get_default_LIB LIB_GDK
 #define gdk_screen_get_monitor_at_point_LIB LIB_GDK
 #define gdk_screen_get_monitor_at_window_LIB LIB_GDK
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c
index bd9d7b5..ad9f01d 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c	
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c	
@@ -554,6 +554,7 @@ char * OS_nativeFunctionNames[] = {
 	"_1gdk_1region_1subtract",
 	"_1gdk_1region_1union",
 	"_1gdk_1region_1union_1with_1rect",
+	"_1gdk_1rgba_1to_1string",
 	"_1gdk_1screen_1get_1default",
 	"_1gdk_1screen_1get_1monitor_1at_1point",
 	"_1gdk_1screen_1get_1monitor_1at_1window",
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h
index 016b472..cb21fb3 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h	
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h	
@@ -564,6 +564,7 @@ typedef enum {
 	_1gdk_1region_1subtract_FUNC,
 	_1gdk_1region_1union_FUNC,
 	_1gdk_1region_1union_1with_1rect_FUNC,
+	_1gdk_1rgba_1to_1string_FUNC,
 	_1gdk_1screen_1get_1default_FUNC,
 	_1gdk_1screen_1get_1monitor_1at_1point_FUNC,
 	_1gdk_1screen_1get_1monitor_1at_1window_FUNC,
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
index a7fb6fe..a1795dd 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java	
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java	
@@ -5492,6 +5492,19 @@ public static final void gdk_region_union_with_rect(long /*int*/ region, GdkRect
 		lock.unlock();
 	}
 }
+/** 
+ * @method flags=dynamic
+ * @param rgba cast=(GdkRGBA *) 
+ */
+public static final native long /*int*/ _gdk_rgba_to_string(GdkRGBA rgba);
+public static final long /*int*/ gdk_rgba_to_string(GdkRGBA rgba) {
+	lock.lock();
+	try {
+		return _gdk_rgba_to_string(rgba);
+	} finally {
+		lock.unlock();
+	}
+}
 /** @method flags=dynamic */
 public static final native long /*int*/ _gdk_screen_get_default();
 public static final long /*int*/ gdk_screen_get_default() {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java
index 4c4b557..e0f4782 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java	
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java	
@@ -64,6 +64,7 @@ public class Composite extends Scrollable {
 	Layout layout;
 	Control[] tabList;
 	int layoutCount, backgroundMode;
+	GdkRGBA background;
 
 	static final String NO_INPUT_METHOD = "org.eclipse.swt.internal.gtk.noInputMethod"; //$NON-NLS-1$
 
@@ -352,6 +353,16 @@ void createHandle (int index, boolean fixed, boolean scrolled) {
 }
 
 @Override
+long /*int*/ gtk_draw (long /*int*/ widget, long /*int*/ cairo) {
+	if (OS.GTK_VERSION >= OS.VERSION(3, 16, 0)) {
+		Rectangle area = getClientArea();
+		long /*int*/ context = OS.gtk_widget_get_style_context(widget);
+		OS.gtk_render_background(context, cairo, area.x, area.y, area.width, area.height);
+	}
+	return super.gtk_draw(widget, cairo);
+}
+
+@Override
 void deregister () {
 	super.deregister ();
 	if (socketHandle != 0) display.removeWidget (socketHandle);
@@ -650,6 +661,23 @@ public Rectangle getClientArea () {
 	return super.getClientArea();
 }
 
+@Override
+GdkColor getContextBackground () {
+	if (OS.GTK_VERSION >= OS.VERSION(3, 16, 0)) {
+		if (background != null) {
+			GdkColor color = new GdkColor ();
+			color.red = (short)(background.red * 0xFFFF);
+			color.green = (short)(background.green * 0xFFFF);
+			color.blue = (short)(background.blue * 0xFFFF);
+			return color;
+		} else {
+			return display.COLOR_WIDGET_BACKGROUND;
+		}
+	} else {
+		return super.getContextBackground();
+	}
+}
+
 /**
  * Returns layout which is associated with the receiver, or
  * null if one has not been set.
@@ -1438,6 +1466,18 @@ public void setBackgroundMode (int mode) {
 }
 
 @Override
+void setBackgroundColor (long /*int*/ context, long /*int*/ handle, GdkRGBA rgba) {
+	if (OS.GTK_VERSION >= OS.VERSION(3, 16, 0)) {
+		background = rgba;
+		String color = gtk_rgba_to_css_string(background);
+		String css = "SwtFixed {background-color: " + color + "}";
+		gtk_css_provider_load_from_css(context, css);
+	} else {
+		super.setBackgroundColor(context, handle, rgba);
+	}
+}
+
+@Override
 int setBounds (int x, int y, int width, int height, boolean move, boolean resize) {
 	int result = super.setBounds (x, y, width, height, move, resize);
 	if ((result & RESIZED) != 0 && layout != null) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java
index ecf2da0..f297659 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java	
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java	
@@ -4096,13 +4096,30 @@ void gtk_css_provider_load_from_css (long /*int*/ context, String css) {
 
 String gtk_rgba_to_css_string (GdkRGBA rgba) {
 	/*
-	 * In GdkRGBA, values are a double between 0-1.<br>
-     * In CSS, values are typically integers between 0-255.<br>
-     * I.e, note, there is a slight loss of precision.
-     * Thus setting/getting color *might* return slight differences.
+	 * In GdkRGBA, values are a double between 0-1.
+	 * In CSS, values are integers between 0-255 for r, g, and b.
+	 * Alpha is still a double between 0-1.
+	 * The final CSS format is: rgba(int, int, int, double)
+	 * Due to this, there is a slight loss of precision.
+	 * Setting/getting with CSS *might* yield slight differences.
 	 */
-	String color = "rgba(" + (int)(rgba.red * 255) + "," + (int)(rgba.green * 255) + "," + (int)(rgba.blue * 255) + "," + (int)(rgba.alpha * 255) + ")";
-	return color;
+	GdkRGBA toConvert;
+	if (rgba != null) {
+		toConvert = rgba;
+	} else {
+		// If we have a null RGBA, set it to the default COLOR_WIDGET_BACKGROUND.
+		GdkColor defaultGdkColor = display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND).handle; 
+		toConvert = new GdkRGBA ();
+		toConvert.alpha = 1.0;
+		toConvert.red = (defaultGdkColor.red & 0xFFFF) / (float)0xFFFF;
+		toConvert.green = (defaultGdkColor.green & 0xFFFF) / (float)0xFFFF;
+		toConvert.blue = (defaultGdkColor.blue & 0xFFFF) / (float)0xFFFF;
+	}
+	long /*int*/ str = OS.gdk_rgba_to_string (toConvert);
+	int length = OS.strlen (str);
+	byte [] buffer = new byte [length];
+	OS.memmove (buffer, str, length);
+	return new String (Converter.mbcsToWcs (null, buffer));
 }
 
 void setBackgroundColor (long /*int*/ handle, GdkColor color) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ToolBar.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ToolBar.java
index 8f6d149..d69f1d6 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ToolBar.java	
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ToolBar.java	
@@ -600,6 +600,16 @@ int setBounds (int x, int y, int width, int height, boolean move, boolean resize
 }
 
 @Override
+void setBackgroundColor (long /*int*/ context, long /*int*/ handle, GdkRGBA rgba) {
+	if (OS.GTK_VERSION >= OS.VERSION(3, 16, 0)) {
+		String css = "GtkToolbar {background-color: " + gtk_rgba_to_css_string(rgba) + "}";
+		gtk_css_provider_load_from_css(context, css);
+	} else {
+		super.setBackgroundColor(context, handle, rgba);
+	}
+}
+
+@Override
 void setFontDescription (long /*int*/ font) {
 	super.setFontDescription (font);
 	ToolItem [] items = getItems ();
-- 
cgit v0.11.2-4-g4a35