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 2dde70fc912..ce16f38691b 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 @@ -8360,6 +8360,16 @@ JNIEXPORT void JNICALL GTK_NATIVE(gtk_1tree_1view_1column_1clear) } #endif +#ifndef NO_gtk_1tree_1view_1column_1clear_1attributes +JNIEXPORT void JNICALL GTK_NATIVE(gtk_1tree_1view_1column_1clear_1attributes) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1) +{ + GTK_NATIVE_ENTER(env, that, gtk_1tree_1view_1column_1clear_1attributes_FUNC); + gtk_tree_view_column_clear_attributes((GtkTreeViewColumn *)arg0, (GtkCellRenderer *)arg1); + GTK_NATIVE_EXIT(env, that, gtk_1tree_1view_1column_1clear_1attributes_FUNC); +} +#endif + #ifndef NO_gtk_1tree_1view_1column_1get_1button JNIEXPORT jlong JNICALL GTK_NATIVE(gtk_1tree_1view_1column_1get_1button) (JNIEnv *env, jclass that, jlong arg0) @@ -10193,6 +10203,18 @@ JNIEXPORT jlong JNICALL OS_NATIVE(G_1OBJECT_1TYPE_1NAME) } #endif +#ifndef NO_G_1PARAM_1SPEC_1VALUE_1TYPE +JNIEXPORT jlong JNICALL OS_NATIVE(G_1PARAM_1SPEC_1VALUE_1TYPE) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + OS_NATIVE_ENTER(env, that, G_1PARAM_1SPEC_1VALUE_1TYPE_FUNC); + rc = (jlong)G_PARAM_SPEC_VALUE_TYPE((GParamSpec *)arg0); + OS_NATIVE_EXIT(env, that, G_1PARAM_1SPEC_1VALUE_1TYPE_FUNC); + return rc; +} +#endif + #ifndef NO_G_1TYPE_1BOOLEAN JNIEXPORT jlong JNICALL OS_NATIVE(G_1TYPE_1BOOLEAN) (JNIEnv *env, jclass that) @@ -12134,6 +12156,22 @@ JNIEXPORT void JNICALL OS_NATIVE(g_1menu_1remove) } #endif +#ifndef NO_g_1object_1class_1find_1property +JNIEXPORT jlong JNICALL OS_NATIVE(g_1object_1class_1find_1property) + (JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1) +{ + jbyte *lparg1=NULL; + jlong rc = 0; + OS_NATIVE_ENTER(env, that, g_1object_1class_1find_1property_FUNC); + if (arg1) if ((lparg1 = (*env)->GetByteArrayElements(env, arg1, NULL)) == NULL) goto fail; + rc = (jlong)g_object_class_find_property((GObjectClass *)arg0, (const gchar *)lparg1); +fail: + if (arg1 && lparg1) (*env)->ReleaseByteArrayElements(env, arg1, lparg1, 0); + OS_NATIVE_EXIT(env, that, g_1object_1class_1find_1property_FUNC); + return rc; +} +#endif + #ifndef NO_g_1object_1get__J_3B_3IJ JNIEXPORT void JNICALL OS_NATIVE(g_1object_1get__J_3B_3IJ) (JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1, jintArray arg2, jlong arg3) 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 1f8c28e57c2..a5a2d0b5356 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 @@ -668,6 +668,7 @@ typedef enum { gtk_1tree_1view_1column_1cell_1get_1position_FUNC, gtk_1tree_1view_1column_1cell_1set_1cell_1data_FUNC, gtk_1tree_1view_1column_1clear_FUNC, + gtk_1tree_1view_1column_1clear_1attributes_FUNC, gtk_1tree_1view_1column_1get_1button_FUNC, gtk_1tree_1view_1column_1get_1fixed_1width_FUNC, gtk_1tree_1view_1column_1get_1reorderable_FUNC, @@ -833,6 +834,7 @@ typedef enum { G_1OBJECT_1GET_1CLASS_FUNC, G_1OBJECT_1TYPE_FUNC, G_1OBJECT_1TYPE_1NAME_FUNC, + G_1PARAM_1SPEC_1VALUE_1TYPE_FUNC, G_1TYPE_1BOOLEAN_FUNC, G_1TYPE_1DOUBLE_FUNC, G_1TYPE_1FLOAT_FUNC, @@ -982,6 +984,7 @@ typedef enum { g_1menu_1item_1set_1submenu_FUNC, g_1menu_1new_FUNC, g_1menu_1remove_FUNC, + g_1object_1class_1find_1property_FUNC, g_1object_1get__J_3B_3IJ_FUNC, g_1object_1get__J_3B_3JJ_FUNC, g_1object_1get_1qdata_FUNC, diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java index 5f240f511bc..a98008b4d86 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java @@ -1973,6 +1973,11 @@ public class GTK extends OS { public static final native void gtk_tree_view_column_cell_set_cell_data(long tree_column, long tree_model, long iter, boolean is_expander, boolean is_expanded); /** @param tree_column cast=(GtkTreeViewColumn *) */ public static final native void gtk_tree_view_column_clear(long tree_column); + /** + * @param tree_column cast=(GtkTreeViewColumn *) + * @param cell_renderer cast=(GtkCellRenderer *) + */ + public static final native void gtk_tree_view_column_clear_attributes(long tree_column, long cell_renderer); /** @param column cast=(GtkTreeViewColumn *) */ public static final native long gtk_tree_view_column_get_button(long column); /** @param column cast=(GtkTreeViewColumn *) */ 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 26d028d2667..9395928ad18 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 @@ -504,6 +504,7 @@ public static String getEnvironmentalVariable (String envVarName) { public static final byte[] spacing = ascii("spacing"); public static final byte[] pixbuf = ascii("pixbuf"); public static final byte[] gicon = ascii("gicon"); + public static final byte[] surface = ascii("surface"); public static final byte[] text = ascii("text"); public static final byte[] xalign = ascii("xalign"); public static final byte[] ypad = ascii("ypad"); @@ -954,6 +955,8 @@ public static boolean isX11 () { public static final native int Call (long func, long arg0, int arg1, int arg2); public static final native long G_OBJECT_GET_CLASS(long object); public static final native long G_OBJECT_TYPE_NAME(long object); +/** @param pspec cast=(GParamSpec *) */ +public static final native long G_PARAM_SPEC_VALUE_TYPE(long pspec); /** @method flags=const */ public static final native long G_TYPE_INVALID(); /** @method flags=const */ @@ -1270,6 +1273,11 @@ public static boolean isX11 () { public static final native int g_log_writer_default(int log_level, long fields, long n_fields, long user_data); /** @param size cast=(gulong) */ public static final native long g_malloc(long size); +/** + * @param oclass cast=(GObjectClass *) + * @param property_name cast=(const gchar *) + */ +public static final native long g_object_class_find_property(long oclass, byte[] property_name); /** * @param object cast=(GObject *) * @param first_property_name cast=(const gchar *),flags=no_out diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java index cdf9d75c0ac..8664247fb65 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java @@ -385,6 +385,7 @@ public void stop() { /* Renderer Subclass */ static long text_renderer_type, pixbuf_renderer_type, toggle_renderer_type; + static long cairo_surface_type; static long text_renderer_info_ptr, pixbuf_renderer_info_ptr, toggle_renderer_info_ptr; static Callback rendererClassInitCallback, rendererRenderCallback, rendererSnapshotCallback; static Callback rendererGetPreferredWidthCallback; @@ -2184,6 +2185,20 @@ long gtk_cell_renderer_toggle_get_type () { return toggle_renderer_type; } +long cairoSurfaceType () { + if (cairo_surface_type == 0) { + // The boxed type of the pixbuf renderer's "surface" property is the one a model column must use + long rendererClass = OS.g_type_class_ref (GTK.GTK_TYPE_CELL_RENDERER_PIXBUF ()); + if (rendererClass != 0) { + long pspec = OS.g_object_class_find_property (rendererClass, OS.surface); + if (pspec != 0) cairo_surface_type = OS.G_PARAM_SPEC_VALUE_TYPE (pspec); + OS.g_type_class_unref (rendererClass); + } + if (cairo_surface_type == 0) SWT.error (SWT.ERROR_NO_HANDLES); + } + return cairo_surface_type; +} + String gtk_css_create_css_color_string (String background, String foreground, int property) { switch (property) { case SWT.FOREGROUND: diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Table.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Table.java index 6b77b808c0c..ed7bb8dc1fd 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Table.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Table.java @@ -234,9 +234,15 @@ long cellDataProc (long tree_column, long cell, long tree_model, long iter, long if (setData) { ptr [0] = 0; if (isPixbuf) { - GTK.gtk_tree_model_get (tree_model, iter, modelIndex + CELL_PIXBUF, ptr, -1); - OS.g_object_set (cell, OS.gicon, ptr [0], 0); - if (ptr [0] != 0) OS.g_object_unref (ptr [0]); + if (useCellSurface ()) { + GTK.gtk_tree_model_get (tree_model, iter, modelIndex + CELL_SURFACE, ptr, -1); + OS.g_object_set (cell, OS.surface, ptr [0], 0); + if (ptr [0] != 0) Cairo.cairo_surface_destroy (ptr [0]); + } else { + GTK.gtk_tree_model_get (tree_model, iter, modelIndex + CELL_PIXBUF, ptr, -1); + OS.g_object_set (cell, OS.gicon, ptr [0], 0); + if (ptr [0] != 0) OS.g_object_unref (ptr [0]); + } } else { GTK.gtk_tree_model_get (tree_model, iter, modelIndex + CELL_TEXT, ptr, -1); if (ptr [0] != 0) { @@ -904,9 +910,8 @@ void createRenderers (long columnHandle, int modelIndex, boolean check, int colu * no images. Fix for Bug 457196. NOTE: this change has been ported to Tables since Tables/Trees both * use the same underlying GTK structure. */ - GTK.gtk_tree_view_column_add_attribute (columnHandle, pixbufRenderer, OS.pixbuf, modelIndex + CELL_PIXBUF); + addPixbufAttributes (columnHandle, pixbufRenderer, modelIndex, useCellSurface ()); if (!ownerDraw) { - GTK.gtk_tree_view_column_add_attribute (columnHandle, pixbufRenderer, OS.cell_background_rgba, BACKGROUND_COLUMN); GTK.gtk_tree_view_column_add_attribute (columnHandle, textRenderer, OS.cell_background_rgba, BACKGROUND_COLUMN); } GTK.gtk_tree_view_column_add_attribute (columnHandle, textRenderer, OS.text, modelIndex + CELL_TEXT); @@ -1101,6 +1106,7 @@ void destroyItem (TableColumn column) { GTK.gtk_list_store_set (modelHandle, iter, modelIndex + CELL_FOREGROUND, (long )0, -1); GTK.gtk_list_store_set (modelHandle, iter, modelIndex + CELL_BACKGROUND, (long )0, -1); GTK.gtk_list_store_set (modelHandle, iter, modelIndex + CELL_FONT, (long )0, -1); + GTK.gtk_list_store_set (modelHandle, iter, modelIndex + CELL_SURFACE, (long )0, -1); Font [] cellFont = item.cellFont; if (cellFont != null) { @@ -1306,7 +1312,7 @@ public int getColumnCount () { // per cell data for (int i=FIRST_COLUMN; i GTK.GTK_TREE_VIEW_GRID_LINES_NONE; } +/** + * GtkCellRendererPixbuf treats "pixbuf" as a scale 1 image, so HiDPI cells bind the + * device scaled "surface" instead. The surface bypasses GTK's insensitive icon effect. + */ +boolean useCellSurface () { + return !GTK.GTK4 && GTK.gtk_widget_get_scale_factor (handle) > 1 + && (state & DISABLED) == 0; +} + +void addPixbufAttributes (long columnHandle, long pixbufRenderer, int modelIndex, boolean surface) { + if (surface) { + GTK.gtk_tree_view_column_add_attribute (columnHandle, pixbufRenderer, OS.surface, modelIndex + CELL_SURFACE); + } else { + GTK.gtk_tree_view_column_add_attribute (columnHandle, pixbufRenderer, OS.pixbuf, modelIndex + CELL_PIXBUF); + } + if (!ownerDraw) { + GTK.gtk_tree_view_column_add_attribute (columnHandle, pixbufRenderer, OS.cell_background_rgba, BACKGROUND_COLUMN); + } +} + +void updateCellImageBinding () { + if (GTK.GTK4 || handle == 0) return; + boolean surface = useCellSurface (); + for (int i=0; iTableItems that are currently * selected in the receiver. The order of the items is unspecified. diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java index 5f5a1e8bda5..ef1bd8840cc 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java @@ -319,9 +319,15 @@ long cellDataProc (long tree_column, long cell, long tree_model, long iter, long if (setData) { if (isPixbuf) { ptr [0] = 0; - GTK.gtk_tree_model_get (tree_model, iter, modelIndex + CELL_PIXBUF, ptr, -1); - OS.g_object_set (cell, OS.gicon, ptr [0], 0); - if (ptr [0] != 0) OS.g_object_unref (ptr [0]); + if (useCellSurface ()) { + GTK.gtk_tree_model_get (tree_model, iter, modelIndex + CELL_SURFACE, ptr, -1); + OS.g_object_set (cell, OS.surface, ptr [0], 0); + if (ptr [0] != 0) Cairo.cairo_surface_destroy (ptr [0]); + } else { + GTK.gtk_tree_model_get (tree_model, iter, modelIndex + CELL_PIXBUF, ptr, -1); + OS.g_object_set (cell, OS.gicon, ptr [0], 0); + if (ptr [0] != 0) OS.g_object_unref (ptr [0]); + } } else { ptr [0] = 0; GTK.gtk_tree_model_get (tree_model, iter, modelIndex + CELL_TEXT, ptr, -1); @@ -1133,9 +1139,8 @@ void createRenderers (long columnHandle, int modelIndex, boolean check, int colu * no images. Fix for Bug 469277 & 476419. NOTE: this change has been ported to Tables since Tables/Trees both * use the same underlying GTK structure. */ - GTK.gtk_tree_view_column_add_attribute (columnHandle, pixbufRenderer, OS.pixbuf, modelIndex + CELL_PIXBUF); + addPixbufAttributes (columnHandle, pixbufRenderer, modelIndex, useCellSurface ()); if (!isOwnerDrawn) { - GTK.gtk_tree_view_column_add_attribute (columnHandle, pixbufRenderer, OS.cell_background_rgba, BACKGROUND_COLUMN); GTK.gtk_tree_view_column_add_attribute (columnHandle, textRenderer, OS.cell_background_rgba, BACKGROUND_COLUMN); } GTK.gtk_tree_view_column_add_attribute (columnHandle, textRenderer, OS.text, modelIndex + CELL_TEXT); @@ -1262,6 +1267,7 @@ void destroyItem (TreeColumn column) { GTK.gtk_tree_store_set (modelHandle, iter, modelIndex + CELL_FOREGROUND, (long )0, -1); GTK.gtk_tree_store_set (modelHandle, iter, modelIndex + CELL_BACKGROUND, (long )0, -1); GTK.gtk_tree_store_set (modelHandle, iter, modelIndex + CELL_FONT, (long )0, -1); + GTK.gtk_tree_store_set (modelHandle, iter, modelIndex + CELL_SURFACE, (long )0, -1); Font [] cellFont = item.cellFont; if (cellFont != null) { @@ -1534,7 +1540,7 @@ public int getColumnCount () { types [i + CELL_FOREGROUND] = GDK.GDK_TYPE_RGBA(); types [i + CELL_BACKGROUND] = GDK.GDK_TYPE_RGBA(); types [i + CELL_FONT] = OS.PANGO_TYPE_FONT_DESCRIPTION (); - types [i + CELL_SURFACE] = OS.G_TYPE_LONG(); + types [i + CELL_SURFACE] = GTK.GTK4 ? OS.G_TYPE_LONG() : display.cairoSurfaceType (); } return types; } @@ -1981,6 +1987,57 @@ public TreeItem getParentItem () { return null; } +/** + * GtkCellRendererPixbuf treats "pixbuf" as a scale 1 image, so HiDPI cells bind the + * device scaled "surface" instead. The surface bypasses GTK's insensitive icon effect. + */ +boolean useCellSurface () { + return !GTK.GTK4 && GTK.gtk_widget_get_scale_factor (handle) > 1 + && (state & DISABLED) == 0; +} + +void addPixbufAttributes (long columnHandle, long pixbufRenderer, int modelIndex, boolean surface) { + if (surface) { + GTK.gtk_tree_view_column_add_attribute (columnHandle, pixbufRenderer, OS.surface, modelIndex + CELL_SURFACE); + } else { + GTK.gtk_tree_view_column_add_attribute (columnHandle, pixbufRenderer, OS.pixbuf, modelIndex + CELL_PIXBUF); + } + if (!isOwnerDrawn) { + GTK.gtk_tree_view_column_add_attribute (columnHandle, pixbufRenderer, OS.cell_background_rgba, BACKGROUND_COLUMN); + } +} + +void updateCellImageBinding () { + if (GTK.GTK4 || handle == 0) return; + boolean surface = useCellSurface (); + for (int i=0; iTreeItems that are currently * selected in the receiver. The order of the items is unspecified.