Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandr Miloslavskiy2019-04-15 14:35:55 +0000
committerEric Williams2019-04-16 14:04:01 +0000
commitf4cff7872b771fc8b6e5080b5b256b174f68de3e (patch)
tree539bdd949e539373ba43faa317dc7c7596b3469c /tests/org.eclipse.swt.tests.gtk/ManualNativeCTests/BugSnippets/Bug_545587_TooltipColor.cpp
parentc64218f83b34c6936c38d867bf5bfa4cfa76fdef (diff)
downloadeclipse.platform.swt-f4cff7872b771fc8b6e5080b5b256b174f68de3e.tar.gz
eclipse.platform.swt-f4cff7872b771fc8b6e5080b5b256b174f68de3e.tar.xz
eclipse.platform.swt-f4cff7872b771fc8b6e5080b5b256b174f68de3e.zip
Bug 546252 - [GTK] Cleanup for tooltip color fixes
Fix: ---- All layers are rendered when background color is estimated. This solves the problem for themes that utilize semi-transparent labels in tooltips, such as 'HighContrast'. NOTE: 'gtk_style_context_get_parent' requires 3.4. However, for Eclipse 4.12 requires at least GTK 3.10, so this can be ignored. Code cleaning: -------------- Deleted tooltip-related CSS parsing code that is now dead. Tests: ------ Added snippets I developed during investigation. Change-Id: Ic4504be60df58f32e32b90a487e28af68853977d Signed-off-by: Alexandr Miloslavskiy <alexandr.miloslavskiy@syntevo.com>
Diffstat (limited to 'tests/org.eclipse.swt.tests.gtk/ManualNativeCTests/BugSnippets/Bug_545587_TooltipColor.cpp')
-rw-r--r--tests/org.eclipse.swt.tests.gtk/ManualNativeCTests/BugSnippets/Bug_545587_TooltipColor.cpp399
1 files changed, 399 insertions, 0 deletions
diff --git a/tests/org.eclipse.swt.tests.gtk/ManualNativeCTests/BugSnippets/Bug_545587_TooltipColor.cpp b/tests/org.eclipse.swt.tests.gtk/ManualNativeCTests/BugSnippets/Bug_545587_TooltipColor.cpp
new file mode 100644
index 0000000000..69cc8f4852
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.gtk/ManualNativeCTests/BugSnippets/Bug_545587_TooltipColor.cpp
@@ -0,0 +1,399 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Syntevo and others. All rights reserved.
+ * The contents of this file are made available under the terms
+ * of the GNU Lesser General Public License (LGPL) Version 2.1 that
+ * accompanies this distribution (lgpl-v21.txt). The LGPL is also
+ * available at http://www.gnu.org/licenses/lgpl.html. If the version
+ * of the LGPL at http://www.gnu.org is different to the version of
+ * the LGPL accompanying this distribution and there is any conflict
+ * between the two license versions, the terms of the LGPL accompanying
+ * this distribution shall govern.
+ *
+ * Contributors:
+ * Syntevo - initial implementation
+ *******************************************************************************/
+#include <gtk/gtk.h>
+#include <cstring>
+#include <string>
+#include <string.h>
+
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+std::string format_GdkRGBA(GdkRGBA a_Color)
+{
+ char buffer[64];
+
+ sprintf
+ (
+ buffer,
+ "{%3d,%3d,%3d,%3d}",
+ (unsigned char)(255 * a_Color.red),
+ (unsigned char)(255 * a_Color.green),
+ (unsigned char)(255 * a_Color.blue),
+ (unsigned char)(255 * a_Color.alpha)
+ );
+
+ return buffer;
+}
+
+void testColors()
+{
+ for (int testBits = 0; testBits < (1 << 4); testBits++)
+ {
+ GdkRGBA colorFore;
+ {
+ GtkWidgetPath* widgetPath = gtk_widget_path_new();
+ gint pathPos = gtk_widget_path_append_type(widgetPath, gtk_tooltip_get_type());
+
+ #if GTK_CHECK_VERSION(3,20,0)
+ if (testBits & 1)
+ gtk_widget_path_iter_set_object_name(widgetPath, pathPos, "tooltip");
+ #else
+ // Silence the warning
+ (void)pathPos;
+ #endif
+
+ if (testBits & 2)
+ gtk_widget_path_append_type(widgetPath, gtk_label_get_type());
+
+ GtkStyleContext* styleContext = gtk_style_context_new();
+ gtk_style_context_set_path(styleContext, widgetPath);
+ gtk_widget_path_free(widgetPath);
+
+ if (testBits & 4)
+ gtk_style_context_add_class(styleContext, GTK_STYLE_CLASS_BACKGROUND);
+
+ if (testBits & 8)
+ gtk_style_context_add_class(styleContext, GTK_STYLE_CLASS_TOOLTIP);
+
+ gtk_style_context_get_color(styleContext, GTK_STATE_FLAG_NORMAL, &colorFore);
+
+ g_object_unref(styleContext);
+ }
+
+ GdkRGBA colorBack;
+ {
+ GtkWidgetPath* widgetPath = gtk_widget_path_new();
+ gint pathPos = gtk_widget_path_append_type(widgetPath, gtk_tooltip_get_type());
+
+ #if GTK_CHECK_VERSION(3,20,0)
+ if (testBits & 1)
+ gtk_widget_path_iter_set_object_name(widgetPath, pathPos, "tooltip");
+ #else
+ // Silence the warning
+ (void)pathPos;
+ #endif
+
+ if (testBits & 2)
+ gtk_widget_path_append_type(widgetPath, gtk_label_get_type());
+
+ GtkStyleContext* styleContext = gtk_style_context_new();
+ gtk_style_context_set_path(styleContext, widgetPath);
+ gtk_widget_path_free(widgetPath);
+
+ if (testBits & 4)
+ gtk_style_context_add_class(styleContext, GTK_STYLE_CLASS_BACKGROUND);
+
+ if (testBits & 8)
+ gtk_style_context_add_class(styleContext, GTK_STYLE_CLASS_TOOLTIP);
+
+ gtk_style_context_get_background_color(styleContext, GTK_STATE_FLAG_NORMAL, &colorBack);
+
+ g_object_unref(styleContext);
+ }
+
+ printf
+ (
+ "%c%c%c%c fore=%s back=%s\n",
+ (testBits & 1) ? '1' : '-',
+ (testBits & 2) ? '2' : '-',
+ (testBits & 4) ? '3' : '-',
+ (testBits & 8) ? '4' : '-',
+ format_GdkRGBA(colorFore).c_str(),
+ format_GdkRGBA(colorBack).c_str()
+ );
+ }
+}
+
+void styleContext_getForeColor(GtkStyleContext* a_StyleContext, GdkRGBA* a_ForeColor)
+{
+ // gtk_style_context_save(a_StyleContext);
+ // gtk_style_context_set_state(a_StyleContext, GTK_STATE_FLAG_NORMAL);
+ gtk_style_context_get_color(a_StyleContext, GTK_STATE_FLAG_NORMAL, a_ForeColor);
+ // gtk_style_context_restore(a_StyleContext);
+}
+
+bool styleContext_hasBackgroundImage(GtkStyleContext* a_StyleContext)
+{
+ GValue valueBackgroundImage = G_VALUE_INIT;
+ gtk_style_context_get_property(a_StyleContext, GTK_STYLE_PROPERTY_BACKGROUND_IMAGE, GTK_STATE_FLAG_NORMAL, &valueBackgroundImage);
+
+ const bool result = (NULL != g_value_get_boxed(&valueBackgroundImage));
+
+ g_value_unset(&valueBackgroundImage);
+
+ return result;
+}
+
+int inversePremultipliedColor(int color, int alpha) {
+ if (alpha == 0) return 0;
+ return (255*color + alpha-1) / alpha;
+}
+
+void renderAllBackgrounds(GtkStyleContext* a_StyleContext, cairo_t* a_Cairo)
+{
+ GtkStyleContext* parentStyleContext = gtk_style_context_get_parent(a_StyleContext);
+ if (parentStyleContext)
+ renderAllBackgrounds(parentStyleContext, a_Cairo);
+
+ gtk_render_background(a_StyleContext, a_Cairo, -50, -50, 100, 100);
+}
+
+void styleContext_estimateBackColor(GtkStyleContext* a_StyleContext, GdkRGBA* a_BackColor)
+{
+ GtkStateFlags state = GTK_STATE_FLAG_NORMAL;
+
+ unsigned char imageBytes[4];
+ {
+ gtk_style_context_save(a_StyleContext);
+ gtk_style_context_set_state(a_StyleContext, state);
+ cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
+ cairo_t* cairo = cairo_create(surface);
+
+ renderAllBackgrounds(a_StyleContext, cairo);
+ cairo_surface_flush(surface);
+ memcpy(imageBytes, cairo_image_surface_get_data(surface), sizeof(imageBytes));
+
+ cairo_surface_destroy(surface);
+ cairo_destroy(cairo);
+ gtk_style_context_restore(a_StyleContext);
+ }
+
+ const unsigned char a = imageBytes[3];
+ const unsigned char r = imageBytes[2];
+ const unsigned char g = imageBytes[1];
+ const unsigned char b = imageBytes[0];
+
+ a_BackColor->alpha = a / 255.0;
+ a_BackColor->red = inversePremultipliedColor(r, a) / 255.0;
+ a_BackColor->green = inversePremultipliedColor(g, a) / 255.0;
+ a_BackColor->blue = inversePremultipliedColor(b, a) / 255.0;
+}
+
+void styleContext_getBackColor(GtkStyleContext* a_StyleContext, GdkRGBA* a_BackColor)
+{
+ gtk_style_context_get_background_color(a_StyleContext, GTK_STATE_FLAG_NORMAL, a_BackColor);
+}
+
+std::string dumpStyleContext(GtkStyleContext* a_StyleContext)
+{
+ // char* contextDump = gtk_style_context_to_string(a_StyleContext, GTK_STYLE_CONTEXT_PRINT_RECURSE);
+
+ const GtkWidgetPath* widgetPath = gtk_style_context_get_path(a_StyleContext);
+ char* contextDump = gtk_widget_path_to_string(widgetPath);
+ std::string result = contextDump;
+ g_free(contextDump);
+
+ return result;
+}
+
+void printTooltipColors(GtkStyleContext* a_StyleContextLabel, GtkStyleContext* a_StyleContextTooltip, const char* a_Caption)
+{
+ const std::string dumpFore = dumpStyleContext(a_StyleContextLabel);
+ const std::string dumpBack = dumpStyleContext(a_StyleContextTooltip);
+
+ GdkRGBA colorFore;
+ styleContext_getForeColor(a_StyleContextLabel, &colorFore);
+
+ const bool hasBackgroundImage = styleContext_hasBackgroundImage(a_StyleContextTooltip);
+
+ GdkRGBA colorBackEstim;
+ styleContext_estimateBackColor(a_StyleContextLabel, &colorBackEstim);
+
+ GdkRGBA colorBackValue;
+ styleContext_getBackColor(a_StyleContextTooltip, &colorBackValue);
+
+ printf
+ (
+ "With %s:\n"
+ "\tlabel = %s\n"
+ "\ttooltip = %s\n"
+ "\t%s = Fore color (via gtk_style_context_get_color(label))\n"
+ "\t%s = Back color (via gtk_render_background(label))\n"
+ "\t%s = Back color (via gtk_style_context_get_background_color(tooltip))\n"
+ "\tbackground-image=%c\n",
+ a_Caption,
+ dumpFore.c_str(),
+ dumpBack.c_str(),
+ format_GdkRGBA(colorFore).c_str(),
+ format_GdkRGBA(colorBackEstim).c_str(),
+ format_GdkRGBA(colorBackValue).c_str(),
+ hasBackgroundImage ? 'Y' : 'N'
+ );
+}
+
+void getTooltipColors_GtkWidgetPath()
+{
+#if GTK_CHECK_VERSION(3,20,0)
+ if (0 != gtk_check_version(3, 20, 0))
+ {
+ // 'gtk_widget_path_iter_set_object_name' was introduced in 3.20.0
+ printf("With GtkWidgetPath: Requires 3.20.0\n");
+ return;
+ }
+
+ // Foreground color is taken from 'tooltip label' css node
+ GtkStyleContext* styleContextLabel = gtk_style_context_new();
+ {
+ GtkWidgetPath* widgetPath = gtk_widget_path_new();
+ gtk_widget_path_append_type(widgetPath, 0);
+ gtk_widget_path_iter_set_object_name(widgetPath, -1, "tooltip");
+ gtk_widget_path_iter_add_class(widgetPath, -1, GTK_STYLE_CLASS_BACKGROUND);
+ gtk_widget_path_append_type(widgetPath, GTK_TYPE_LABEL);
+ gtk_style_context_set_path(styleContextLabel, widgetPath);
+ gtk_widget_path_free(widgetPath);
+ }
+
+ // Background color is taken from 'tooltip.background' css node
+ GtkStyleContext* styleContextTooltip = gtk_style_context_new();
+ {
+ GtkWidgetPath* widgetPath = gtk_widget_path_new();
+ gtk_widget_path_append_type(widgetPath, 0);
+ gtk_widget_path_iter_set_object_name(widgetPath, -1, "tooltip");
+ gtk_widget_path_iter_add_class(widgetPath, -1, GTK_STYLE_CLASS_BACKGROUND);
+ gtk_style_context_set_path(styleContextTooltip, widgetPath);
+ gtk_widget_path_free(widgetPath);
+ }
+
+ // Print
+ printTooltipColors(styleContextLabel, styleContextTooltip, "GtkWidgetPath");
+
+ // Destroy temporary style contexts
+ g_object_unref(styleContextLabel);
+ g_object_unref(styleContextTooltip);
+#endif // GTK_CHECK_VERSION(3,20,0)
+}
+
+void getTooltipColors_GtkTooltipWindow()
+{
+#if GTK_CHECK_VERSION(3,19,2)
+ if (0 != gtk_check_version(3, 19, 2))
+ {
+ // 'GtkTooltipWindow' was introduced in 3.19.2
+ printf("With GtkTooltipWindow: Requires 3.19.2\n");
+ return;
+ }
+
+ // Force 'GtkTooltip' to register 'GtkTooltipWindow' class
+ {
+ GType typeTooltip = gtk_tooltip_get_type();
+ GObject* tooltip = (GObject*)g_object_new(typeTooltip, NULL);
+ g_object_unref(tooltip);
+ }
+
+ // Obtain GType of non-exported type 'GtkTooltipWindow'
+ GType typeTooltipWindow = g_type_from_name("GtkTooltipWindow");
+ if (0 == typeTooltipWindow)
+ {
+ printf("With GtkTooltipWindow: g_type_from_name() failed\n");
+ return;
+ }
+
+ // Create temporary tooltip
+ GtkWidget* tooltip = (GtkWidget*)g_object_new(typeTooltipWindow, NULL);
+
+ // Create temporary label in tooltip
+ GtkWidget* tooltipLabel = (GtkWidget*)g_object_new(GTK_TYPE_LABEL, NULL);
+ gtk_widget_set_parent(tooltipLabel, tooltip);
+
+ // Obtain style contexts
+ GtkStyleContext* styleContextLabel = gtk_widget_get_style_context(tooltipLabel);
+ GtkStyleContext* styleContextTooltip = gtk_widget_get_style_context(tooltip);
+
+ // Print
+ printTooltipColors(styleContextLabel, styleContextTooltip, "GtkTooltipWindow");
+
+ // Also destroys child label
+ gtk_widget_destroy(tooltip);
+#endif // GTK_CHECK_VERSION(3,19,2)
+}
+
+void getTooltipColors_TooltipSetCustom()
+{
+ // Create a temporary tooltip
+ GType typeTooltip = gtk_tooltip_get_type();
+ GtkTooltip* tooltip = (GtkTooltip*)g_object_new(typeTooltip, NULL);
+
+ // Add temporary label as custom control into tooltip
+ GtkWidget* customLabel = (GtkWidget*)g_object_new(GTK_TYPE_LABEL, NULL);
+ gtk_tooltip_set_custom(tooltip, customLabel);
+
+ // Find tooltip window, using custom widget as entry point
+ GtkWidget* tooltipBox = gtk_widget_get_parent(customLabel);
+ GtkWidget* tooltipWindow = gtk_widget_get_parent(tooltipBox);
+
+ // Obtain style contexts
+ // For label, just use temporary label; this is easier then finding the original label
+ GtkStyleContext* styleContextLabel = gtk_widget_get_style_context(customLabel);
+ GtkStyleContext* styleContextTooltip = gtk_widget_get_style_context(tooltipWindow);
+
+ // Print
+ printTooltipColors(styleContextLabel, styleContextTooltip, "TooltipSetCustom");
+
+ // Cleanup
+ // customLabel is owned by tooltip and will be destroyed automatically
+ g_object_unref(tooltip);
+}
+
+bool isThemeAvailable()
+{
+ const char* themeName = g_getenv("GTK_THEME");
+
+ if (!themeName)
+ return true;
+
+ if (0 == strcasecmp(themeName, "Adwaita"))
+ return true;
+
+ // When GTK doesn't find a theme, it simply loads Adwaita.
+ GtkCssProvider* selectedTheme = gtk_css_provider_get_named(themeName, NULL);
+ GtkCssProvider* adwaitaTheme = gtk_css_provider_get_named("Adwaita", NULL);
+
+ char* selectedThemeString = gtk_css_provider_to_string(selectedTheme);
+ char* adwaitaThemeString = gtk_css_provider_to_string(adwaitaTheme);
+ const bool isAdwaita =(0 == strcmp(selectedThemeString, adwaitaThemeString));
+ g_free(selectedThemeString);
+ g_free(adwaitaThemeString);
+
+ if (isAdwaita)
+ {
+ printf("Error: Theme %s not found\n", themeName);
+ return false;
+ }
+
+ return true;
+}
+
+int main(int argc, char* argv[])
+{
+ gtk_init(&argc, &argv);
+
+ if (!isThemeAvailable())
+ return 0;
+
+ printf
+ (
+ "GTK version: %d.%d.%d\n",
+ gtk_get_major_version(),
+ gtk_get_minor_version(),
+ gtk_get_micro_version()
+ );
+
+ // testColors();
+ getTooltipColors_GtkWidgetPath();
+ getTooltipColors_GtkTooltipWindow();
+ getTooltipColors_TooltipSetCustom();
+
+ return 0;
+}
+

Back to the top