src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c
changeset 53800 76668d618a99
parent 53665 2121afe70084
child 53802 e3451d08503a
--- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c	Thu Feb 14 20:20:49 2019 +0000
+++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c	Fri Feb 15 10:58:57 2019 +0530
@@ -258,6 +258,7 @@
 
 static gboolean gtk3_version_3_10 = TRUE;
 static gboolean gtk3_version_3_14 = FALSE;
+static gboolean gtk3_version_3_20 = FALSE;
 
 GtkApi* gtk3_load(JNIEnv *env, const char* lib_name)
 {
@@ -400,6 +401,18 @@
         }
         gtk3_version_3_14 = !fp_gtk_check_version(3, 14, 0);
 
+        if (!fp_gtk_check_version(3, 20, 0)) {
+            gtk3_version_3_20 = TRUE;
+            fp_gtk_widget_path_copy = dl_symbol("gtk_widget_path_copy");
+            fp_gtk_widget_path_new = dl_symbol("gtk_widget_path_new");
+            fp_gtk_widget_path_append_type = dl_symbol("gtk_widget_path_append_type");
+            fp_gtk_widget_path_iter_set_object_name = dl_symbol("gtk_widget_path_iter_set_object_name");
+            fp_gtk_style_context_set_path = dl_symbol("gtk_style_context_set_path");
+            fp_gtk_widget_path_unref = dl_symbol("gtk_widget_path_unref");
+            fp_gtk_style_context_get_path = dl_symbol("gtk_style_context_get_path");
+            fp_gtk_style_context_new = dl_symbol("gtk_style_context_new");
+        }
+
         fp_gdk_window_create_similar_surface =
                       dl_symbol("gdk_window_create_similar_surface");
         fp_gtk_settings_get_for_screen =
@@ -561,7 +574,6 @@
                                                 "gtk_combo_box_new_with_entry");
         fp_gtk_separator_tool_item_new = dlsym(gtk3_libhandle,
                                                  "gtk_separator_tool_item_new");
-
         fp_g_list_append = dl_symbol("g_list_append");
         fp_g_list_free = dl_symbol("g_list_free");
         fp_g_list_free_full = dl_symbol("g_list_free_full");
@@ -1362,6 +1374,90 @@
     return result;
 }
 
+static void append_element (GtkWidgetPath *path, const gchar *selector)
+{
+    fp_gtk_widget_path_append_type (path, G_TYPE_NONE);
+    fp_gtk_widget_path_iter_set_object_name (path, -1, selector);
+}
+
+static GtkWidgetPath* createWidgetPath(const GtkWidgetPath* path) {
+    if (path == NULL) {
+        return fp_gtk_widget_path_new();
+    } else {
+        return fp_gtk_widget_path_copy(path);
+    }
+}
+
+static GtkStyleContext* get_style(WidgetType widget_type, const gchar *detail)
+{
+    if (!gtk3_version_3_20) {
+        gtk3_widget = gtk3_get_widget(widget_type);
+        GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+        fp_gtk_style_context_save (context);
+        if (detail != 0) {
+             transform_detail_string(detail, context);
+        }
+        return context;
+    } else {
+        gtk3_widget = gtk3_get_widget(widget_type);
+        GtkStyleContext* widget_context = fp_gtk_widget_get_style_context (gtk3_widget);
+        GtkWidgetPath *path = NULL;
+        if (detail != 0) {
+            if (strcmp(detail, "checkbutton") == 0) {
+                path = createWidgetPath (fp_gtk_style_context_get_path (widget_context));
+                append_element(path, "check");
+            } else if (strcmp(detail, "radiobutton") == 0) {
+                path = createWidgetPath (fp_gtk_style_context_get_path (widget_context));
+                append_element(path, "radio");
+            } else if (strcmp(detail, "vscale") == 0 || strcmp(detail, "hscale") == 0) {
+                path = createWidgetPath (fp_gtk_style_context_get_path (widget_context));
+                append_element(path, "slider");
+            } else if (strcmp(detail, "trough") == 0) {
+                //This is a fast solution to the scrollbar trough not being rendered properly
+                if (widget_type == HSCROLL_BAR || widget_type == HSCROLL_BAR_TRACK ||
+                    widget_type == VSCROLL_BAR || widget_type == VSCROLL_BAR_TRACK) {
+                    path = createWidgetPath (NULL);
+                } else {
+                    path = createWidgetPath (fp_gtk_style_context_get_path (widget_context));
+                }
+                append_element(path, detail);
+            } else if (strcmp(detail, "bar") == 0) {
+                path = createWidgetPath (fp_gtk_style_context_get_path (widget_context));
+                append_element(path, "trough");
+                append_element(path, "progress");
+            } else if (strcmp(detail, "vscrollbar") == 0 || strcmp(detail, "hscrollbar") == 0) {
+                path = createWidgetPath (fp_gtk_style_context_get_path (widget_context));
+                append_element(path, "button");
+            } else if (strcmp(detail, "check") == 0) {
+                path = createWidgetPath (NULL);
+                append_element(path, detail);
+            } else if (strcmp(detail, "option") == 0) {
+                path = createWidgetPath (NULL);
+                append_element(path, "radio");
+            } else {
+                path = createWidgetPath (fp_gtk_style_context_get_path (widget_context));
+                append_element(path, detail);
+            }
+        } else {
+            path = createWidgetPath (fp_gtk_style_context_get_path (widget_context));
+        }
+
+        GtkStyleContext *context = fp_gtk_style_context_new ();
+        fp_gtk_style_context_set_path (context, path);
+        fp_gtk_widget_path_unref (path);
+        return context;
+    }
+}
+
+static void disposeOrRestoreContext(GtkStyleContext *context)
+{
+    if (!gtk3_version_3_20) {
+        fp_gtk_style_context_restore (context);
+    } else {
+        fp_g_object_unref (context);
+    }
+}
+
 static void gtk3_paint_arrow(WidgetType widget_type, GtkStateType state_type,
         GtkShadowType shadow_type, const gchar *detail,
         gint x, gint y, gint width, gint height,
@@ -1509,13 +1605,9 @@
      */
     gtk3_set_direction(gtk3_widget, dir);
 
-    GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
-    fp_gtk_style_context_save (context);
-
-    transform_detail_string(detail, context);
+    GtkStyleContext* context = get_style(widget_type, detail);
 
     GtkStateFlags flags = get_gtk_flags(state_type);
-
     if (shadow_type == GTK_SHADOW_IN && widget_type != COMBO_BOX_ARROW_BUTTON) {
         flags |= GTK_STATE_FLAG_ACTIVE;
     }
@@ -1532,23 +1624,31 @@
         fp_gtk_style_context_add_class (context, "default");
     }
 
+    if (fp_gtk_style_context_has_class(context, "trough")) {
+        flags |= GTK_STATE_FLAG_BACKDROP;
+    }
+
     fp_gtk_style_context_set_state (context, flags);
 
-    if (fp_gtk_style_context_has_class(context, "progressbar")) {
-        fp_gtk_render_activity (context, cr, x, y, width, height);
-    } else {
-        fp_gtk_render_background (context, cr, x, y, width, height);
-        if (shadow_type != GTK_SHADOW_NONE) {
-            fp_gtk_render_frame(context, cr, x, y, width, height);
-        }
+    fp_gtk_render_background (context, cr, x, y, width, height);
+    if (shadow_type != GTK_SHADOW_NONE) {
+        fp_gtk_render_frame(context, cr, x, y, width, height);
     }
 
-    fp_gtk_style_context_restore (context);
+    disposeOrRestoreContext(context);
+
     /*
      * Reset the text direction to the default value so that we don't
      * accidentally affect other operations and widgets.
      */
     gtk3_set_direction(gtk3_widget, GTK_TEXT_DIR_LTR);
+
+    //This is a fast solution to the scrollbar trough not being rendered properly
+    if ((widget_type == HSCROLL_BAR || widget_type == HSCROLL_BAR_TRACK ||
+        widget_type == VSCROLL_BAR || widget_type == VSCROLL_BAR_TRACK) && detail != 0) {
+        gtk3_paint_box(widget_type, state_type, shadow_type, NULL,
+                    x, y, width, height, synth_state, dir);
+    }
 }
 
 static void gtk3_paint_box_gap(WidgetType widget_type, GtkStateType state_type,
@@ -1580,23 +1680,19 @@
 static void gtk3_paint_check(WidgetType widget_type, gint synth_state,
         const gchar *detail, gint x, gint y, gint width, gint height)
 {
-    gtk3_widget = gtk3_get_widget(widget_type);
-
-    GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
-
-    fp_gtk_style_context_save (context);
+    GtkStyleContext* context = get_style(widget_type, detail);
 
     GtkStateFlags flags = get_gtk_state_flags(synth_state);
     if (gtk3_version_3_14 && (synth_state & SELECTED)) {
-        flags = GTK_STATE_FLAG_CHECKED;
+        flags &= ~GTK_STATE_FLAG_SELECTED;
+        flags |= GTK_STATE_FLAG_CHECKED;
     }
     fp_gtk_style_context_set_state(context, flags);
 
-    fp_gtk_style_context_add_class (context, "check");
-
-    fp_gtk_render_check (context, cr, x, y, width, height);
-
-    fp_gtk_style_context_restore (context);
+    fp_gtk_render_background(context, cr, x, y, width, height);
+    fp_gtk_render_frame(context, cr, x, y, width, height);
+    fp_gtk_render_check(context, cr, x, y, width, height);
+    disposeOrRestoreContext(context);
 }
 
 
@@ -1684,7 +1780,6 @@
     gtk3_widget = gtk3_get_widget(widget_type);
 
     GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
-
     fp_gtk_style_context_save (context);
 
     if (detail != 0) {
@@ -1787,25 +1882,19 @@
 static void gtk3_paint_option(WidgetType widget_type, gint synth_state,
         const gchar *detail, gint x, gint y, gint width, gint height)
 {
-     gtk3_widget = gtk3_get_widget(widget_type);
-
-     GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
-
-     fp_gtk_style_context_save (context);
+     GtkStyleContext* context = get_style(widget_type, detail);
 
      GtkStateFlags flags = get_gtk_state_flags(synth_state);
      if (gtk3_version_3_14 && (synth_state & SELECTED)) {
-         flags = GTK_STATE_FLAG_CHECKED;
+         flags &= ~GTK_STATE_FLAG_SELECTED;
+         flags |= GTK_STATE_FLAG_CHECKED;
      }
      fp_gtk_style_context_set_state(context, flags);
 
-     if (detail != 0) {
-         transform_detail_string(detail, context);
-     }
-
+     fp_gtk_render_background(context, cr, x, y, width, height);
+     fp_gtk_render_frame(context, cr, x, y, width, height);
      fp_gtk_render_option(context, cr, x, y, width, height);
-
-     fp_gtk_style_context_restore (context);
+     disposeOrRestoreContext(context);
 }
 
 static void gtk3_paint_shadow(WidgetType widget_type, GtkStateType state_type,
@@ -1864,15 +1953,7 @@
         gint x, gint y, gint width, gint height, GtkOrientation orientation,
         gboolean has_focus)
 {
-    gtk3_widget = gtk3_get_widget(widget_type);
-
-    GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
-
-    fp_gtk_style_context_save (context);
-
-    if (detail) {
-       transform_detail_string(detail, context);
-    }
+    GtkStyleContext *context = get_style(widget_type, detail);
 
     GtkStateFlags flags = get_gtk_flags(state_type);
 
@@ -1886,9 +1967,10 @@
 
     fp_gtk_style_context_set_state (context, flags);
 
+    fp_gtk_render_background (context, cr, x, y, width, height);
+    fp_gtk_render_frame(context, cr, x, y, width, height);
     (*fp_gtk_render_slider)(context, cr, x, y, width, height, orientation);
-
-    fp_gtk_style_context_restore (context);
+    disposeOrRestoreContext(context);
 }
 
 static void gtk3_paint_background(WidgetType widget_type,