diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/Clipboard.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/Clipboard.java index 6cd70304a42..1412721c787 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/Clipboard.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/Clipboard.java @@ -15,7 +15,6 @@ import org.eclipse.swt.*; -import org.eclipse.swt.graphics.*; import org.eclipse.swt.internal.*; import org.eclipse.swt.internal.gtk.*; import org.eclipse.swt.internal.gtk3.*; @@ -39,15 +38,24 @@ public class Clipboard { static long GTKCLIPBOARD; static long GTKPRIMARYCLIPBOARD; + /** + * GTK3 only + */ private static long TARGET; static { - GTKCLIPBOARD = GTK.GTK4 ? GDK.gdk_display_get_clipboard(GDK.gdk_display_get_default()) : GTK3.gtk_clipboard_get (GDK.GDK_NONE); - byte[] buffer = Converter.wcsToMbcs("PRIMARY", true); - long primary = GTK.GTK4 ? 0 : GDK.gdk_atom_intern(buffer, false); - GTKPRIMARYCLIPBOARD = GTK.GTK4 ? GDK.gdk_display_get_primary_clipboard(GDK.gdk_display_get_default()) : GTK3.gtk_clipboard_get(primary); - buffer = Converter.wcsToMbcs("TARGETS", true); - TARGET = GTK.GTK4 ? 0 : GDK.gdk_atom_intern(buffer, false); + if (GTK.GTK4) { + GTKCLIPBOARD = GDK.gdk_display_get_clipboard(GDK.gdk_display_get_default()); + GTKPRIMARYCLIPBOARD = GDK.gdk_display_get_primary_clipboard(GDK.gdk_display_get_default()); + TARGET = 0; + } else { + GTKCLIPBOARD = GTK3.gtk_clipboard_get(GDK.GDK_NONE); + byte[] buffer = Converter.wcsToMbcs("PRIMARY", true); + long primary = GDK.gdk_atom_intern(buffer, false); + GTKPRIMARYCLIPBOARD = GTK3.gtk_clipboard_get(primary); + buffer = Converter.wcsToMbcs("TARGETS", true); + TARGET = GDK.gdk_atom_intern(buffer, false); + } } /** @@ -188,8 +196,13 @@ public void clearContents() { */ public void clearContents(int clipboards) { checkWidget(); - ClipboardProxy proxy = ClipboardProxy._getInstance(display); - proxy.clear(this, clipboards); + if (GTK.GTK4) { + ClipboardProxyGTK4 proxy = ClipboardProxyGTK4._getInstance(display); + proxy.clear(this, clipboards); + } else { + ClipboardProxy proxy = ClipboardProxy._getInstance(display); + proxy.clear(this, clipboards); + } } /** @@ -290,14 +303,12 @@ public Object getContents(Transfer transfer) { * @since 3.1 */ public Object getContents(Transfer transfer, int clipboards) { - checkWidget(); - if (transfer == null) DND.error(SWT.ERROR_NULL_ARGUMENT); - - if(GTK.GTK4) { - Object result = getContents_gtk4(transfer, clipboards); - return result; + if (GTK.GTK4) { + return getContents_gtk4(transfer, clipboards); } + checkWidget(); + if (transfer == null) DND.error(SWT.ERROR_NULL_ARGUMENT); long selection_data = 0; int[] typeIds = transfer.getTypeIds(); boolean textTransfer = transfer.getTypeNames()[0].equals("UTF8_STRING"); @@ -327,65 +338,11 @@ public Object getContents(Transfer transfer, int clipboards) { } private Object getContents_gtk4(Transfer transfer, int clipboards) { + checkWidget(); + if (transfer == null) DND.error(SWT.ERROR_NULL_ARGUMENT); - long contents = GTK4.gdk_clipboard_get_content(Clipboard.GTKCLIPBOARD); - if(contents == 0) return null; - long value = OS.g_malloc (OS.GValue_sizeof ()); - C.memset (value, 0, OS.GValue_sizeof ()); - - //Pasting of text (TextTransfer/RTFTransfer) - if(transfer.getTypeNames()[0].equals("text/plain") || transfer.getTypeNames()[0].equals("text/rtf")) { - OS.g_value_init(value, OS.G_TYPE_STRING()); - if (!GTK4.gdk_content_provider_get_value (contents, value, null)) return null; - long cStr = OS.g_value_get_string(value); - long [] items_written = new long [1]; - long utf16Ptr = OS.g_utf8_to_utf16(cStr, -1, null, items_written, null); - OS.g_free(cStr); - if (utf16Ptr == 0) return null; - int length = (int)items_written[0]; - char[] buffer = new char[length]; - C.memmove(buffer, utf16Ptr, length * 2); - OS.g_free(utf16Ptr); - String str = new String(buffer); - if(transfer.getTypeNames()[0].equals("text/rtf") && !str.contains("{\\rtf1")) { - return null; - } - if(transfer.getTypeNames()[0].equals("text/plain") && str.contains("{\\rtf1")){ - return null; - } - return str; - } - //Pasting of Image - if(transfer.getTypeIds()[0] == (int)GDK.GDK_TYPE_PIXBUF()) { - ImageData imgData = null; - OS.g_value_init(value, GDK.GDK_TYPE_PIXBUF()); - if (!GTK4.gdk_content_provider_get_value (contents, value, null)) return null; - long pixbufObj = OS.g_value_get_object(value); - if (pixbufObj != 0) { - Image img = Image.gtk_new_from_pixbuf(Display.getCurrent(), SWT.BITMAP, pixbufObj); - imgData = img.getImageData(); - img.dispose(); - } - return imgData; - } - //Pasting of HTML - if(transfer.getTypeNames()[0].equals("text/html")) { - OS.g_value_init(value, OS.G_TYPE_STRING()); - if (!GTK4.gdk_content_provider_get_value (contents, value, null)) return null; - long cStr = OS.g_value_get_string(value); - long [] items_written = new long [1]; - long utf16Ptr = OS.g_utf8_to_utf16(cStr, -1, null, items_written, null); - OS.g_free(cStr); - if (utf16Ptr == 0) return null; - int length = (int)items_written[0]; - char[] buffer = new char[length]; - C.memmove(buffer, utf16Ptr, length * 2); - OS.g_free(utf16Ptr); - String str = new String(buffer); - return str; - } - //TODO: [GTK4] Other cases - return null; + ClipboardProxyGTK4 proxy = ClipboardProxyGTK4._getInstance(display); + return proxy.getData(this, transfer, clipboards); } /** @@ -525,9 +482,16 @@ public void setContents(Object[] data, Transfer[] dataTypes, int clipboards) { DND.error(SWT.ERROR_INVALID_ARGUMENT); } } - ClipboardProxy proxy = ClipboardProxy._getInstance(display); - if (!proxy.setData(this, data, dataTypes, clipboards)) { - DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD); + if (GTK.GTK4) { + ClipboardProxyGTK4 proxy = ClipboardProxyGTK4._getInstance(display); + if (!proxy.setData(this, data, dataTypes, clipboards)) { + DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD); + } + } else { + ClipboardProxy proxy = ClipboardProxy._getInstance(display); + if (!proxy.setData(this, data, dataTypes, clipboards)) { + DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD); + } } } @@ -623,8 +587,10 @@ public TransferData[] getAvailableTypes(int clipboards) { public String[] getAvailableTypeNames() { checkWidget(); if(GTK.GTK4) { + // TODO make sure this code works with new GTK4 impl long formatsCStr = GTK4.gdk_content_formats_to_string(GTK4.gdk_clipboard_get_formats(Clipboard.GTKCLIPBOARD)); String formatsStr = Converter.cCharPtrToJavaString(formatsCStr, true); + System.out.println(formatsStr); String[] types = formatsStr.split(" "); return types; } @@ -673,6 +639,7 @@ private int[] getAvailableClipboardTypes () { return gtk3_getAvailableTypes(GTKCLIPBOARD); } +// TODO make sure this code works with new GTK4 impl private int[] gtk4_getAvailableTypes(long clipboard) { long formats = GTK4.gdk_clipboard_get_formats(clipboard); long[] n_gtypes = new long[1]; @@ -723,4 +690,6 @@ long gtk_clipboard_wait_for_contents(long clipboard, long target) { } return selection_data; } + + } diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ClipboardProxy.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ClipboardProxy.java index fd61b6c8eaa..92068b23c49 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ClipboardProxy.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ClipboardProxy.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. + * Copyright (c) 2000, 2025 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -14,14 +14,15 @@ package org.eclipse.swt.dnd; -import org.eclipse.swt.*; -import org.eclipse.swt.graphics.*; import org.eclipse.swt.internal.*; import org.eclipse.swt.internal.gtk.*; import org.eclipse.swt.internal.gtk3.*; -import org.eclipse.swt.internal.gtk4.*; import org.eclipse.swt.widgets.*; +/** + * Clipboard proxy used to copy data to the clipboard in GTK3 only + * @see ClipboardProxyGTK4 the GTK4 version + */ class ClipboardProxy { /* Data is not flushed to the clipboard immediately. * This class will remember the data and provide it when requested. @@ -31,7 +32,7 @@ class ClipboardProxy { Object[] primaryClipboardData; Transfer[] primaryClipboardDataTypes; - long clipboardOwner = GTK.GTK4 ? GTK4.gtk_window_new() : GTK3.gtk_window_new(GTK.GTK_WINDOW_TOPLEVEL); + long clipboardOwner = GTK3.gtk_window_new(GTK.GTK_WINDOW_TOPLEVEL); Display display; Clipboard activeClipboard = null; @@ -42,6 +43,9 @@ class ClipboardProxy { static String ID = "CLIPBOARD PROXY OBJECT"; //$NON-NLS-1$ static ClipboardProxy _getInstance(final Display display) { + if (GTK.GTK4) { + throw new UnsupportedOperationException("Illegal attempt to use GTK3 ClipboardProxy on GTK4"); + } ClipboardProxy proxy = (ClipboardProxy) display.getData(ID); if (proxy != null) return proxy; proxy = new ClipboardProxy(display); @@ -55,7 +59,7 @@ static ClipboardProxy _getInstance(final Display display) { return proxy; } -ClipboardProxy(Display display) { +private ClipboardProxy(Display display) { this.display = display; getFunc = new Callback( this, "getFunc", 4); //$NON-NLS-1$ clearFunc = new Callback( this, "clearFunc", 2); //$NON-NLS-1$ @@ -71,11 +75,7 @@ void clear (Clipboard owner, int clipboards) { } void gtk_gdk_clipboard_clear(long clipboard) { - if (GTK.GTK4) { - GDK.gdk_clipboard_set_content(clipboard, 0); - } else { - GTK3.gtk_clipboard_clear(clipboard); - } + GTK3.gtk_clipboard_clear(clipboard); } long clearFunc(long clipboard,long user_data_or_owner){ @@ -95,10 +95,10 @@ long clearFunc(long clipboard,long user_data_or_owner){ void dispose () { if (display == null) return; if (activeClipboard != null) { - if(!GTK.GTK4) GTK3.gtk_clipboard_store(Clipboard.GTKCLIPBOARD); + GTK3.gtk_clipboard_store(Clipboard.GTKCLIPBOARD); } if (activePrimaryClipboard != null) { - if(!GTK.GTK4) GTK3.gtk_clipboard_store(Clipboard.GTKPRIMARYCLIPBOARD); + GTK3.gtk_clipboard_store(Clipboard.GTKPRIMARYCLIPBOARD); } display = null; if (getFunc != null ) getFunc.dispose(); @@ -110,11 +110,7 @@ void dispose () { primaryClipboardData = null; primaryClipboardDataTypes = null; if (clipboardOwner != 0) { - if (GTK.GTK4) { - GTK4.gtk_window_destroy(clipboardOwner); - } else { - GTK3.gtk_widget_destroy(clipboardOwner); - } + GTK3.gtk_widget_destroy(clipboardOwner); } clipboardOwner = 0; } @@ -148,9 +144,6 @@ long getFunc(long clipboard, long selection_data, long info, long user_data_or_o } boolean setData(Clipboard owner, Object[] data, Transfer[] dataTypes, int clipboards) { - - if(GTK.GTK4) return setData_gtk4(owner, data, dataTypes, clipboards); - GtkTargetEntry[] entries = new GtkTargetEntry [0]; long pTargetsList = 0; try { @@ -219,66 +212,4 @@ boolean setData(Clipboard owner, Object[] data, Transfer[] dataTypes, int clipbo if (pTargetsList != 0) OS.g_free(pTargetsList); } } - -private boolean setData_gtk4(Clipboard owner, Object[] data, Transfer[] dataTypes, int clipboards) { - boolean result = false; - long [] providers = new long[0]; - for (int i = 0; i < dataTypes.length; i++) { - Transfer transfer = dataTypes[i]; - String[] typeNames = transfer.getTypeNames(); - //Build the GdkContentProvider for each and store in array - long provider = setProviderFromType(typeNames[0], data[i]); - if(provider != 0) { - long[] tmp = new long [providers.length + 1]; - System.arraycopy(providers, 0, tmp, 0, providers.length); - tmp[providers.length] = provider; - providers = tmp; - } - } - //Build the GdkContentProvider Union - if (providers.length == 0) return false; - long union = GTK4.gdk_content_provider_new_union(providers, providers.length); - - if ((clipboards & DND.CLIPBOARD) != 0){ - clipboardData = data; - clipboardDataTypes = dataTypes; - result = GTK4.gdk_clipboard_set_content(Clipboard.GTKCLIPBOARD, union); - activeClipboard = owner; - } - return result; -} - -private long setProviderFromType(String string, Object data) { - long provider = 0; - - if (data == null ) SWT.error(SWT.ERROR_NULL_ARGUMENT); - else { - if(string.equals("text/plain") || string.equals("text/rtf")) { - long value = OS.g_malloc (OS.GValue_sizeof()); - C.memset (value, 0, OS.GValue_sizeof ()); - OS.g_value_init(value, OS.G_TYPE_STRING()); - OS.g_value_set_string(value, Converter.javaStringToCString((String)data)); - provider = GTK4.gdk_content_provider_new_for_value(value); - } - if(string.equals("PIXBUF")) { - if(!(data instanceof ImageData)) DND.error(DND.ERROR_INVALID_DATA); - ImageData imgData = (ImageData)data; - Image image = new Image(Display.getCurrent(), imgData); - long pixbuf = ImageList.createPixbuf(image); - if (pixbuf != 0) { - provider = GTK4.gdk_content_provider_new_typed(GDK.GDK_TYPE_PIXBUF(), pixbuf); - } - image.dispose(); - } - if(string.equals("text/html")) { - long value = OS.g_malloc (OS.GValue_sizeof()); - C.memset (value, 0, OS.GValue_sizeof ()); - OS.g_value_init(value, OS.G_TYPE_STRING()); - OS.g_value_set_string(value, Converter.javaStringToCString((String)data)); - provider = GTK4.gdk_content_provider_new_for_value(value); - } - - } - return provider; -} } diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ClipboardProxyGTK4.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ClipboardProxyGTK4.java new file mode 100644 index 00000000000..46ed9757674 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ClipboardProxyGTK4.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2000, 2025 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.dnd; + +import org.eclipse.swt.dnd.ContentProviders.*; +import org.eclipse.swt.internal.*; +import org.eclipse.swt.internal.gtk.*; +import org.eclipse.swt.internal.gtk4.*; +import org.eclipse.swt.widgets.*; + +/** + * Clipboard proxy used to copy data to the clipboard in GTK4 only + * + * @see ClipboardProxy the GTK3 version + */ +class ClipboardProxyGTK4 { + private static String ID = "CLIPBOARD PROXY OBJECT"; //$NON-NLS-1$ + + private Display display; + private Clipboard activeClipboard = null; + private Clipboard activePrimaryClipboard = null; + private final ContentProviders contentProviders = ContentProviders.getInstance(); + + static ClipboardProxyGTK4 _getInstance(final Display display) { + if (!GTK.GTK4) { + throw new UnsupportedOperationException("Illegal attempt to use GTK4 ClipboardProxy on GTK3"); + } + ClipboardProxyGTK4 proxy = (ClipboardProxyGTK4) display.getData(ID); + if (proxy != null) + return proxy; + proxy = new ClipboardProxyGTK4(display); + display.setData(ID, proxy); + display.disposeExec(() -> { + ClipboardProxyGTK4 clipbordProxy = (ClipboardProxyGTK4) display.getData(ID); + if (clipbordProxy == null) + return; + display.setData(ID, null); + clipbordProxy.dispose(); + }); + return proxy; + } + + private ClipboardProxyGTK4(Display display) { + this.display = display; + } + + void clear(Clipboard owner, int clipboards) { + if ((clipboards & DND.CLIPBOARD) != 0 && activeClipboard == owner) { + gtk_gdk_clipboard_clear(Clipboard.GTKCLIPBOARD); + } + if ((clipboards & DND.SELECTION_CLIPBOARD) != 0 && activePrimaryClipboard == owner) { + gtk_gdk_clipboard_clear(Clipboard.GTKPRIMARYCLIPBOARD); + } + } + + private void gtk_gdk_clipboard_clear(long clipboard) { + // This only clears content if we were owner (i.e. when gdk_clipboard_is_local() + // == true) + GDK.gdk_clipboard_set_content(clipboard, 0); + } + + void dispose() { + if (display == null) { + return; + } + // TODO - before completing disposal, consider storing data to global clipboard + // See + // https://github.com/eclipse-platform/eclipse.platform.swt/issues/2126#issuecomment-3312739514 + display = null; + + } + + boolean setData(Clipboard owner, Object[] data, Transfer[] dataTypes, int clipboards) { + // TODO: free providers + long providers = contentProviders.createContentProviders(data, dataTypes, + CLIPBOARD_TYPE.fromDNDConstants(clipboards), display); + if (providers == 0) { + return false; + } + + boolean result = false; + if ((clipboards & DND.CLIPBOARD) != 0) { + long clipboard = clipboards == DND.SELECTION_CLIPBOARD ? Clipboard.GTKPRIMARYCLIPBOARD + : Clipboard.GTKCLIPBOARD; + result = GTK4.gdk_clipboard_set_content(clipboard, providers); + if (clipboards == DND.SELECTION_CLIPBOARD) { + activePrimaryClipboard = owner; + } else { + activeClipboard = owner; + } + } + return result; + + } + + public Object getData(Clipboard owner, Transfer transfer, int clipboards) { + + long clipboard = clipboards == DND.SELECTION_CLIPBOARD ? Clipboard.GTKPRIMARYCLIPBOARD : Clipboard.GTKCLIPBOARD; + long gType = contentProviders.getGType(transfer); + + System.out.println("About to run gdk_clipboard_read_value_async"); + Object value = new SyncFinishUtil<>().run(display, new SyncFinishCallback<>() { + @Override + public void async(long result) { + GTK4.gdk_clipboard_read_value_async(clipboard, gType, OS.G_PRIORITY_DEFAULT, 0, result, 0); + } + + @Override + public Object await(long result) { + long gvalue = GTK4.gdk_clipboard_read_value_finish(clipboard, result, null); + if (gvalue == 0) { + return null; + } + return contentProviders.getObject(gvalue); + } + }); + + if (value == null) { + // nothing on clipboard, or nothing that can be mapped to transfer's type + return null; + } + + return value; + } +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ContentProviders.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ContentProviders.java new file mode 100644 index 00000000000..7fc9dfd8187 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ContentProviders.java @@ -0,0 +1,366 @@ +/******************************************************************************* + * Copyright (c) 2000, 2025 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.swt.dnd; + +import java.lang.reflect.*; +import java.util.*; + +import org.eclipse.swt.internal.*; +import org.eclipse.swt.internal.gtk.*; +import org.eclipse.swt.internal.gtk4.*; +import org.eclipse.swt.widgets.*; + +/** + * Manages GdkContentProviders + * and the (de)serializers they rely on + */ +class ContentProviders { + public static enum CLIPBOARD_TYPE { + CLIPBOARD(1), PRIMARYCLIPBOARD(2), DRAG(3); + + private final long sourceId; + private final Map data = new HashMap<>(); + private Display display = null; + + CLIPBOARD_TYPE(long id) { + this.sourceId = id; + } + + /** + * Return the DESTINATION instance matching the clipboards using the constants + * {@link DND#CLIPBOARD} and {@link DND#SELECTION_CLIPBOARD} + */ + public static CLIPBOARD_TYPE fromDNDConstants(int clipboards) { + if (clipboards == DND.CLIPBOARD) + return CLIPBOARD; + if (clipboards == DND.SELECTION_CLIPBOARD) + return PRIMARYCLIPBOARD; + // the clipboards should have been error checked for validity before entering + // this method + throw new RuntimeException("Error - invalid clipboards"); + } + + /** + * Returns the DESTINATION matching the given sourceId + */ + public static CLIPBOARD_TYPE fromSourceId(long sourceId) { + CLIPBOARD_TYPE[] values = CLIPBOARD_TYPE.values(); + for (CLIPBOARD_TYPE destination : values) { + if (destination.sourceId == sourceId) { + return destination; + } + } + return null; + } + } + + /** + * The life-time of the serializers in GTK4 (Gdk) are the life-time of the + * process so we use a singleton to store the mapping data that is needed. + */ + private static ContentProviders instance = new ContentProviders(); + + /* + * The types registered with {@link #registerType(String)} on GTK4. Using + * TreeMap to make the maps sorted to ease debugging + */ + final private Map ID_TO_CONTENTTYPE = new TreeMap<>(); + final private Map CONTENTTYPE_TO_ID = new TreeMap<>(); + // start at 1 because 0 is the null formatName + private int typeIndex = 1; + + // These normally need disposal, but since this class is a singleton it isn't + // disposed. + Callback gdkContentSerializeFunc; + Callback gdkContentDeserializeFunc; + + /** + * All transfers registered with the GTK serializers + * + * Key is the transfer obtained with {@link #transferKey(Transfer)} + */ + private Map registeredTransfers = new TreeMap<>(); + + private Object lastDeserializedObject; + + private ContentProviders() { + gdkContentSerializeFunc = new Callback(this, "gdkContentSerializeFunc", void.class, new Type[] { long.class }); //$NON-NLS-1$ + gdkContentDeserializeFunc = new Callback(this, "gdkContentDeserializeFunc", void.class, //$NON-NLS-1$ + new Type[] { long.class }); + } + + public static ContentProviders getInstance() { + return instance; + } + + /** + * Called by {@link Transfer#registerType(String)} only + */ + public int registerType(String formatName) { + if (formatName == null) { + return 0; + } + Integer id = CONTENTTYPE_TO_ID.get(formatName); + if (id == null) { + id = typeIndex++; + CONTENTTYPE_TO_ID.put(formatName, id); + ID_TO_CONTENTTYPE.put(id, formatName); + } + return id; + } + + public long createContentProviders(Object[] data, Transfer[] transfers, CLIPBOARD_TYPE id, Display display) { + id.data.clear(); + id.display = display; + long[] providers = new long[transfers.length]; + for (int i = 0; i < transfers.length; i++) { + Transfer transfer = transfers[i]; + registerTransfer(transfer); + + // gvalue represents a data + transfer pair, with the + // gtype we can extract the transfer type, and that + // plus id can extract the data + long gvalue = OS.create_gvalue(transfer.gtype, id.sourceId); + // TODO free gvalue (probably when we free the union of providers, see TODO + // below) + providers[i] = GTK4.gdk_content_provider_new_for_value(gvalue); + id.data.put(transferKey(transfer), data[i]); + } + + // TODO free union of providers (note that gdk_content_provider_new_union takes + // ownership of providers array) + return GTK4.gdk_content_provider_new_union(providers, providers.length); + } + + void gdkContentSerializeFunc(long pSerializer) { + GdkContentSerializer serializer = new GdkContentSerializer(pSerializer); + + Transfer transfer = getTransfer(serializer); + CLIPBOARD_TYPE fromSourceId = CLIPBOARD_TYPE.fromSourceId(serializer.source_id()); + if (fromSourceId == null) { + // TODO failure here - where did this data come from? How are we asked to + // serialize data + // we didn't start with + // TODO make a GError like this??? or throw exception? Is this only a + // programming error? +// GError *error = g_error_new (G_IO_ERROR, +// G_IO_ERROR_NOT_FOUND, +// "Could not convert data from %s to %s", +// g_type_name (gdk_content_serializer_get_gtype (serializer)), +// gdk_content_serializer_get_mime_type (serializer)); +// serializer.return_error(error); + throw new RuntimeException("this should be unreachable??? - see TODOs above this line"); + } + Object object = fromSourceId.data.get(transferKey(transfer)); + Display display = fromSourceId.display; + String mime_type = serializer.mime_type(); + Integer typeObject = CONTENTTYPE_TO_ID.get(mime_type); + int type = typeObject == null ? 0 : typeObject; + + // Convert the Java object to a C array... + TransferData transferData = new TransferData(); + transferData.type = type; + transfer.javaToNative(object, transferData); + + // ...write the C array to the output stream of the serializer + new AsyncFinishUtil().run(display, new AsyncReadyCallback() { + @Override + public void async(long result) { + OS.g_output_stream_write_all_async(serializer.output_stream(), transferData.pValue, transferData.length, + serializer.priority(), serializer.cancellable(), result, 0); + } + + @Override + public long await(long result) { + long[] error = new long[1]; + boolean finish = OS.g_output_stream_write_all_finish(serializer.output_stream(), result, null, error); + if (!finish) { + serializer.return_error(error[0]); + } else { + serializer.return_success(); + } + OS.g_free(transferData.pValue); + return 0; + } + }); + } + + private Transfer getTransfer(GdkContentSerializer serializer) { + long gtype = serializer.gtype(); + long namePtr = OS.g_type_name(gtype); + String transferName = Converter.cCharPtrToJavaString(namePtr, false); + Transfer transfer = registeredTransfers.get(transferName); + if (transfer == null) { +// TODO make a GError like this??? or throw exception? Is this only a programming error? +// GError *error = g_error_new (G_IO_ERROR, +// G_IO_ERROR_NOT_FOUND, +// "Could not convert data from %s to %s", +// g_type_name (gdk_content_serializer_get_gtype (serializer)), +// gdk_content_serializer_get_mime_type (serializer)); +// GTK4.gdk_content_serializer_return_error(serializer, namePtr); + throw new RuntimeException("Could not convert data because transfer of id " + transferName + " missing"); + } + return transfer; + } + + void gdkContentDeserializeFunc(long pDeserializer) { + System.out.println("gdkContentDeserializeFunc"); + GdkContentDeserializer deserializer = new GdkContentDeserializer(pDeserializer); + + Transfer transfer = getTransfer(deserializer); + String mime_type = deserializer.mime_type(); + Integer typeObject = CONTENTTYPE_TO_ID.get(mime_type); + int type = typeObject == null ? 0 : typeObject; + + Display display = Display.getCurrent(); // TODO where to get display from? Is this OK? + + long memoryStream = OS.g_memory_output_stream_new_resizable(); + System.out.println("About to run g_output_stream_splice_async"); + new AsyncFinishUtil().run(display, new AsyncReadyCallback() { + @Override + public void async(long result) { + OS.g_output_stream_splice_async(memoryStream, deserializer.input_stream(), + OS.G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | OS.G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, + deserializer.priority(), deserializer.cancellable(), result, 0); + } + + @Override + public long await(long result) { + long[] error = new long[1]; + long spliced = OS.g_output_stream_splice_finish(memoryStream, result, null); + if (spliced < 0) { + // TODO save object better (see TODO where lastDeserializedObject is read) + ContentProviders.this.lastDeserializedObject = null; + deserializer.return_error(error[0]); + } else { + TransferData transferData = new TransferData(); + transferData.type = type; + // TODO this downcast is probably ok, but an overflow error should be generated + // if someone tries to copy/paste > 2G of data + transferData.length = (int) OS.g_memory_output_stream_get_data_size(memoryStream); + transferData.pValue = OS.g_memory_output_stream_get_data(memoryStream); + transferData.format = 8; + Object object = transfer.nativeToJava(transferData); + // TODO save object better (see TODO where lastDeserializedObject is read) + System.out.println("Storing " + object); + ContentProviders.this.lastDeserializedObject = object; + deserializer.return_success(); + } + return 0; + } + }); + } + + private Transfer getTransfer(GdkContentDeserializer deserializer) { + long gtype = deserializer.gtype(); + long namePtr = OS.g_type_name(gtype); + String transferName = Converter.cCharPtrToJavaString(namePtr, false); + Transfer transfer = registeredTransfers.get(transferName); + if (transfer == null) { +// TODO make a GError like this??? or throw exception? Is this only a programming error? +// GError *error = g_error_new (G_IO_ERROR, +// G_IO_ERROR_NOT_FOUND, +// "Could not convert data from %s to %s", +// g_type_name (gdk_content_serializer_get_gtype (serializer)), +// gdk_content_serializer_get_mime_type (serializer)); +// GTK4.gdk_content_serializer_return_error(serializer, namePtr); + throw new RuntimeException("Could not convert data because transfer of id " + transferName + " missing"); + } + return transfer; + } + + private void registerTransfer(Transfer transfer) { + String name = transferKey(transfer); + if (registeredTransfers.containsKey(name)) { + return; + } + registeredTransfers.put(name, transfer); + transfer.gtype = OS.register_gtype_for_name(name); + String[] mimeTypes = transfer.getTypeNames(); + for (int i = 0; i < mimeTypes.length; i++) { + String mimeType = mimeTypes[i]; + GTK4.gdk_content_register_serializer(transfer.gtype, mimeType, gdkContentSerializeFunc.getAddress(), 0, 0); + GTK4.gdk_content_register_deserializer(mimeType, transfer.gtype, gdkContentDeserializeFunc.getAddress(), 0, + 0); + } + } + + private String transferKey(Transfer transfer) { + // The value of the name here is used to help debugging the code. + // The only important thing is that the name is unique which is achieved by + // appending transfer.id + return "SWTTransfer_" + transfer.getClass().getSimpleName() + "_" + transfer.id; + } + + public long getGType(Transfer transfer) { + registerTransfer(transfer); + return transfer.gtype; + } + + public Object getObject(long gvalue) { + + long namePtr = OS.G_VALUE_TYPE_NAME(gvalue); + String transferName = Converter.cCharPtrToJavaString(namePtr, false); + Transfer transfer = registeredTransfers.get(transferName); + if (transfer != null) { + long g_value_get_boxed = OS.g_value_get_boxed(gvalue); + CLIPBOARD_TYPE fromSourceId = CLIPBOARD_TYPE.fromSourceId(g_value_get_boxed); + if (fromSourceId != null) { + Object object = fromSourceId.data.get(transferKey(transfer)); + return object; + } + } + + // TODO support multiple deserialized objects - we should really be able to + // align a + // gvalue in GTK memory to a specific Java object here. For now return the last + // thing deserialized + return lastDeserializedObject; + } + +// private long setProviderFromType(String string, Object data) { +// long provider = 0; +// +// if (data == null) +// SWT.error(SWT.ERROR_NULL_ARGUMENT); +// else { +// if (string.equals("text/plain") || string.equals("text/rtf")) { +// long value = OS.g_malloc(OS.GValue_sizeof()); +// C.memset(value, 0, OS.GValue_sizeof()); +// OS.g_value_init(value, OS.G_TYPE_STRING()); +// OS.g_value_set_string(value, Converter.javaStringToCString((String) data)); +// provider = GTK4.gdk_content_provider_new_for_value(value); +// } +// if (string.equals("PIXBUF")) { +// if (!(data instanceof ImageData)) +// DND.error(DND.ERROR_INVALID_DATA); +// ImageData imgData = (ImageData) data; +// Image image = new Image(Display.getCurrent(), imgData); +// long pixbuf = ImageList.createPixbuf(image); +// if (pixbuf != 0) { +// provider = GTK4.gdk_content_provider_new_typed(GDK.GDK_TYPE_PIXBUF(), pixbuf); +// } +// image.dispose(); +// } +// if (string.equals("text/html")) { +// long value = OS.g_malloc(OS.GValue_sizeof()); +// C.memset(value, 0, OS.GValue_sizeof()); +// OS.g_value_init(value, OS.G_TYPE_STRING()); +// OS.g_value_set_string(value, Converter.javaStringToCString((String) data)); +// provider = GTK4.gdk_content_provider_new_for_value(value); +// } +// +// } +// return provider; +// } + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/GdkContentDeserializer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/GdkContentDeserializer.java new file mode 100644 index 00000000000..07d207a3682 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/GdkContentDeserializer.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2000, 2025 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.swt.dnd; + +import org.eclipse.swt.internal.*; +import org.eclipse.swt.internal.gtk4.*; + +/** + * Wrapper for GDK class GdkContentDeserializer with convenience methods to aid in + * writing {@link Transfer}s for GTK4 + */ +class GdkContentDeserializer { + + private long deserializer; + + public GdkContentDeserializer(long deserializer) { + this.deserializer = deserializer; + } + + public long gtype() { + return GTK4.gdk_content_deserializer_get_gtype(deserializer); + } + + public String mime_type() { + return Converter.cCharPtrToJavaString(GTK4.gdk_content_deserializer_get_mime_type(deserializer), false); + } + + public long input_stream() { + return GTK4.gdk_content_deserializer_get_input_stream(deserializer); + + } + + public int priority() { + return GTK4.gdk_content_deserializer_get_priority(deserializer); + } + + public long cancellable() { + return GTK4.gdk_content_deserializer_get_cancellable(deserializer); + } + + public void return_success() { + GTK4.gdk_content_deserializer_return_success(deserializer); + } + + public void return_error(long error) { + GTK4.gdk_content_deserializer_return_error(deserializer, error); + } +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/GdkContentSerializer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/GdkContentSerializer.java new file mode 100644 index 00000000000..cbb70233caa --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/GdkContentSerializer.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2000, 2025 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.swt.dnd; + +import org.eclipse.swt.internal.*; +import org.eclipse.swt.internal.gtk.*; +import org.eclipse.swt.internal.gtk4.*; + +/** + * Wrapper for GDK class GdkContentSerializer with convenience methods to aid in + * writing {@link Transfer}s for GTK4 + */ +class GdkContentSerializer { + private long serializer; + + public GdkContentSerializer(long serializer) { + this.serializer = serializer; + } + + /** + * Return the unboxed value stored in the GValue + * + * This is only suitable for getting the source id when used with GValues + * created by {@link OS#create_gvalue(long, long)} + */ + public long source_id() { + long gvalue = gvalue(); + long source = OS.g_value_get_boxed(gvalue); + return source; + } + + public String mime_type() { + return Converter.cCharPtrToJavaString(GTK4.gdk_content_serializer_get_mime_type(serializer), false); + } + + public long gtype() { + return GTK4.gdk_content_serializer_get_gtype(serializer); + } + + public long gvalue() { + return GTK4.gdk_content_serializer_get_value(serializer); + } + + public long output_stream() { + return GTK4.gdk_content_serializer_get_output_stream(serializer); + } + + public int priority() { + return GTK4.gdk_content_serializer_get_priority(serializer); + } + + public long cancellable() { + return GTK4.gdk_content_serializer_get_cancellable(serializer); + } + + public void return_success() { + GTK4.gdk_content_serializer_return_success(serializer); + } + + public void return_error(long error) { + GTK4.gdk_content_serializer_return_error(serializer, error); + } +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ImageTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ImageTransfer.java index a58b0b35631..760fd13e269 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ImageTransfer.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ImageTransfer.java @@ -40,27 +40,27 @@ public class ImageTransfer extends ByteArrayTransfer { private static ImageTransfer _instance = new ImageTransfer(); private static final String JPEG = "image/jpeg"; //$NON-NLS-1$ - private static final int JPEG_ID = GTK.GTK4 ? 0: registerType(JPEG); + private static final int JPEG_ID = registerType(JPEG); private static final String PNG = "image/png"; //$NON-NLS-1$ - private static final int PNG_ID = GTK.GTK4 ? 0:registerType(PNG); + private static final int PNG_ID = registerType(PNG); private static final String BMP = "image/bmp"; //$NON-NLS-1$ - private static final int BMP_ID = GTK.GTK4 ? 0:registerType(BMP); + private static final int BMP_ID = registerType(BMP); private static final String EPS = "image/eps"; //$NON-NLS-1$ - private static final int EPS_ID = GTK.GTK4 ? 0:registerType(EPS); + private static final int EPS_ID = registerType(EPS); private static final String PCX = "image/pcx"; //$NON-NLS-1$ - private static final int PCX_ID = GTK.GTK4 ? 0:registerType(PCX); + private static final int PCX_ID = registerType(PCX); private static final String PPM = "image/ppm"; //$NON-NLS-1$ - private static final int PPM_ID = GTK.GTK4 ? 0:registerType(PPM); + private static final int PPM_ID = registerType(PPM); private static final String RGB = "image/ppm"; //$NON-NLS-1$ - private static final int RGB_ID = GTK.GTK4 ? 0:registerType(RGB); + private static final int RGB_ID = registerType(RGB); private static final String TGA = "image/tga"; //$NON-NLS-1$ - private static final int TGA_ID = GTK.GTK4 ? 0:registerType(TGA); + private static final int TGA_ID = registerType(TGA); private static final String XBM = "image/xbm"; //$NON-NLS-1$ - private static final int XBM_ID = GTK.GTK4 ? 0:registerType(XBM); + private static final int XBM_ID = registerType(XBM); private static final String XPM = "image/xpm"; //$NON-NLS-1$ - private static final int XPM_ID = GTK.GTK4 ? 0:registerType(XPM); + private static final int XPM_ID = registerType(XPM); private static final String XV = "image/xv"; //$NON-NLS-1$ - private static final int XV_ID = GTK.GTK4 ? 0:registerType(XV); + private static final int XV_ID = registerType(XV); private ImageTransfer() {} @@ -156,17 +156,11 @@ public Object nativeToJava(TransferData transferData) { @Override protected int[] getTypeIds(){ - if(GTK.GTK4) { - return new int[] {(int) GDK.GDK_TYPE_PIXBUF()}; - } return new int[]{PNG_ID, BMP_ID, EPS_ID, JPEG_ID, PCX_ID, PPM_ID, RGB_ID, TGA_ID, XBM_ID, XPM_ID, XV_ID}; } @Override protected String[] getTypeNames(){ - if(GTK.GTK4) { - return new String[]{"PIXBUF"}; - } return new String[]{PNG, BMP, EPS, JPEG, PCX, PPM, RGB, TGA, XBM, XPM, XV}; } diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/RTFTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/RTFTransfer.java index 586ff586da7..8bac1243f79 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/RTFTransfer.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/RTFTransfer.java @@ -63,6 +63,10 @@ public static RTFTransfer getInstance () { */ @Override public void javaToNative (Object object, TransferData transferData){ + if (GTK.GTK4) { + javaToNativeGTK4(object, transferData); + return; + } transferData.result = 0; if (!checkRTF(object) || !isSupportedType(transferData)) { DND.error(DND.ERROR_INVALID_DATA); @@ -78,6 +82,14 @@ public void javaToNative (Object object, TransferData transferData){ transferData.result = 1; } + +private void javaToNativeGTK4(Object object, TransferData transferData) { + if (!checkRTF(object) || !isSupportedType(transferData)) { + DND.error(DND.ERROR_INVALID_DATA); + } + super.javaToNative(Converter.wcsToMbcs((String) object, false), transferData); +} + /** * This implementation of nativeToJava converts a platform specific * representation of RTF text to a java String. @@ -90,6 +102,8 @@ public void javaToNative (Object object, TransferData transferData){ */ @Override public Object nativeToJava(TransferData transferData){ + if (GTK.GTK4) return nativeToJavaGTK4(transferData); + if ( !isSupportedType(transferData) || transferData.pValue == 0 ) return null; int size = transferData.format * transferData.length / 8; if (size == 0) return null; @@ -101,6 +115,14 @@ public Object nativeToJava(TransferData transferData){ return (end == -1) ? string : string.substring(0, end); } +private Object nativeToJavaGTK4(TransferData transferData) { + Object buffer = super.nativeToJava(transferData); + if (buffer instanceof byte[] bytes) { + return new String(Converter.mbcsToWcs(bytes)); + } + return null; +} + @Override protected int[] getTypeIds() { if(GTK.GTK4) { diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TextTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TextTransfer.java index a745aa13026..ff24259e540 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TextTransfer.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TextTransfer.java @@ -42,11 +42,13 @@ public class TextTransfer extends ByteArrayTransfer { private static final String COMPOUND_TEXT = "COMPOUND_TEXT"; //$NON-NLS-1$ private static final String UTF8_STRING = "UTF8_STRING"; //$NON-NLS-1$ private static final String STRING = "STRING"; //$NON-NLS-1$ + private static final String TEXT_PLAIN = "text/plain"; //RFC-1341 private static final String TEXT_PLAIN_UTF8 = "text/plain;charset=utf-8"; //RFC-1341 - private static final int COMPOUND_TEXT_ID = GTK.GTK4 ? 0 : registerType(COMPOUND_TEXT); - private static final int UTF8_STRING_ID = GTK.GTK4 ? 0 : registerType(UTF8_STRING); - private static final int STRING_ID = GTK.GTK4 ? 0 : registerType(STRING); - private static final int TEXT_PLAIN_UTF8_ID = GTK.GTK4 ? 0 : registerType(TEXT_PLAIN_UTF8); + private static final int COMPOUND_TEXT_ID = registerType(COMPOUND_TEXT); + private static final int UTF8_STRING_ID = registerType(UTF8_STRING); + private static final int STRING_ID = registerType(STRING); + private static final int TEXT_PLAIN_ID = registerType(TEXT_PLAIN); + private static final int TEXT_PLAIN_UTF8_ID = registerType(TEXT_PLAIN_UTF8); private TextTransfer() {} @@ -71,6 +73,10 @@ public static TextTransfer getInstance () { */ @Override public void javaToNative (Object object, TransferData transferData) { + if (GTK.GTK4) { + javaToNativeGTK4(object, transferData); + return; + } transferData.result = 0; if (!checkText(object) || !isSupportedType(transferData)) { DND.error(DND.ERROR_INVALID_DATA); @@ -111,6 +117,13 @@ public void javaToNative (Object object, TransferData transferData) { } +private void javaToNativeGTK4(Object object, TransferData transferData) { + if (!checkText(object) || !isSupportedType(transferData)) { + DND.error(DND.ERROR_INVALID_DATA); + } + super.javaToNative(Converter.wcsToMbcs((String) object, false), transferData); +} + /** * This implementation of nativeToJava converts a platform specific * representation of plain text to a java String. @@ -122,6 +135,8 @@ public void javaToNative (Object object, TransferData transferData) { */ @Override public Object nativeToJava(TransferData transferData){ + if (GTK.GTK4) return nativeToJavaGTK4(transferData); + if (!isSupportedType(transferData) || transferData.pValue == 0) return null; long [] list = new long [1]; int count = GDK.gdk_text_property_to_utf8_list_for_display(GDK.gdk_display_get_default(), transferData.type, transferData.format, transferData.pValue, transferData.length, list); @@ -139,10 +154,18 @@ public Object nativeToJava(TransferData transferData){ return (end == -1) ? string : string.substring(0, end); } +private Object nativeToJavaGTK4(TransferData transferData) { + Object buffer = super.nativeToJava(transferData); + if (buffer instanceof byte[] bytes) { + return new String(Converter.mbcsToWcs(bytes)); + } + return null; +} + @Override protected int[] getTypeIds() { if(GTK.GTK4) { - return new int[] {(int) OS.G_TYPE_STRING()}; + return new int[] {TEXT_PLAIN_UTF8_ID, TEXT_PLAIN_ID, STRING_ID}; } if (OS.isX11()) { return new int[] {UTF8_STRING_ID, COMPOUND_TEXT_ID, STRING_ID}; @@ -153,7 +176,7 @@ protected int[] getTypeIds() { @Override protected String[] getTypeNames() { if(GTK.GTK4) { - return new String[] {"text/plain", STRING}; + return new String[] {TEXT_PLAIN_UTF8, TEXT_PLAIN, STRING}; } if (OS.isX11()) { return new String[] {UTF8_STRING, COMPOUND_TEXT, STRING}; diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/Transfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/Transfer.java index 5cf4b739982..0f74f298983 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/Transfer.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/Transfer.java @@ -34,6 +34,22 @@ */ public abstract class Transfer { +private static int nextId = 1; +/** + * Unique id of the transfer type. Used by GTK4 implementation to map + * data in the C/GTK side back to Java. + */ +/* package */ final int id; +/** + * GType registered with GDK for this transfer. Every Transfer type + * is associated with a GType so that SWT knows which transfer to use + */ +/* package */ long gtype; + +public Transfer() { + id = nextId++; +} + /** * Returns a list of the platform specific data types that can be converted using * this transfer agent. @@ -133,6 +149,10 @@ public abstract class Transfer { * @return the unique identifier associated with this data type */ public static int registerType(String formatName){ + if (GTK.GTK4) { + return ContentProviders.getInstance().registerType(formatName); + } + if (formatName == null) return GDK.GDK_NONE; byte[] buffer = Converter.wcsToMbcs(formatName, true); return (int)GDK.gdk_atom_intern(buffer, false); diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TransferData.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TransferData.java index 3ff822475e1..e806ce5813c 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TransferData.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TransferData.java @@ -13,7 +13,6 @@ *******************************************************************************/ package org.eclipse.swt.dnd; - /** * The TransferData class is a platform specific data structure for * describing the type and the contents of data being converted by a transfer agent. @@ -71,7 +70,7 @@ public class TransferData { * platforms and should never be accessed from application code. *

* - * This is most commonly 8 bits. + * This is most commonly 8 bits, and on GTK4 is always 8 bits. * * @noreference This field is not intended to be referenced by clients. */ @@ -107,5 +106,4 @@ public class TransferData { * @noreference This field is not intended to be referenced by clients. */ public int result; - } diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/atk.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/atk.c index 5780bf4fe31..053bd0c722f 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/atk.c +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/atk.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2022 IBM Corporation and others. All rights reserved. + * Copyright (c) 2000, 2025 IBM Corporation 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 diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4.c index 3ebcddc354a..71a2db65a1f 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4.c +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4.c @@ -50,6 +50,77 @@ JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1clipboard_1get_1formats) } #endif +#ifndef NO_gdk_1clipboard_1is_1local +JNIEXPORT jboolean JNICALL GTK4_NATIVE(gdk_1clipboard_1is_1local) + (JNIEnv *env, jclass that, jlong arg0) +{ + jboolean rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1clipboard_1is_1local_FUNC); + rc = (jboolean)gdk_clipboard_is_local((GdkClipboard*)arg0); + GTK4_NATIVE_EXIT(env, that, gdk_1clipboard_1is_1local_FUNC); + return rc; +} +#endif + +#ifndef NO_gdk_1clipboard_1read_1async +JNIEXPORT void JNICALL GTK4_NATIVE(gdk_1clipboard_1read_1async) + (JNIEnv *env, jclass that, jlong arg0, jobjectArray arg1, jint arg2, jlong arg3, jlong arg4, jlong arg5) +{ + char **lparg1=NULL + GTK4_NATIVE_ENTER(env, that, gdk_1clipboard_1read_1async_FUNC); + if (arg1) if ((lparg1 = swt_getArrayOfStringsUTF(env, arg1)) == NULL) goto fail; + gdk_clipboard_read_async((GdkClipboard*)arg0, (const char **)lparg1, (int)arg2, (GCancellable *)arg3, (GAsyncReadyCallback)arg4, (gpointer)arg5); +fail: + if (arg1 && lparg1) swt_releaseArrayOfStringsUTF(env, arg1, lparg1); + GTK4_NATIVE_EXIT(env, that, gdk_1clipboard_1read_1async_FUNC); +} +#endif + +#ifndef NO_gdk_1clipboard_1read_1finish +JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1clipboard_1read_1finish) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlongArray arg2, jlongArray arg3) +{ + jlong *lparg2=NULL; + jlong *lparg3=NULL; + jlong rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1clipboard_1read_1finish_FUNC); + if (arg2) if ((lparg2 = (*env)->GetLongArrayElements(env, arg2, NULL)) == NULL) goto fail; + if (arg3) if ((lparg3 = (*env)->GetLongArrayElements(env, arg3, NULL)) == NULL) goto fail; + rc = (jlong)gdk_clipboard_read_finish((GdkClipboard*)arg0, (GAsyncResult *)arg1, (const char**)lparg2, (GError **)lparg3); +fail: + if (arg3 && lparg3) (*env)->ReleaseLongArrayElements(env, arg3, lparg3, 0); + if (arg2 && lparg2) (*env)->ReleaseLongArrayElements(env, arg2, lparg2, 0); + GTK4_NATIVE_EXIT(env, that, gdk_1clipboard_1read_1finish_FUNC); + return rc; +} +#endif + +#ifndef NO_gdk_1clipboard_1read_1value_1async +JNIEXPORT void JNICALL GTK4_NATIVE(gdk_1clipboard_1read_1value_1async) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jlong arg3, jlong arg4, jlong arg5) +{ + GTK4_NATIVE_ENTER(env, that, gdk_1clipboard_1read_1value_1async_FUNC); + gdk_clipboard_read_value_async((GdkClipboard*)arg0, (GType)arg1, (int)arg2, (GCancellable *)arg3, (GAsyncReadyCallback)arg4, (gpointer)arg5); + GTK4_NATIVE_EXIT(env, that, gdk_1clipboard_1read_1value_1async_FUNC); +} +#endif + +#ifndef NO_gdk_1clipboard_1read_1value_1finish +JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1clipboard_1read_1value_1finish) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlongArray arg2) +{ + jlong *lparg2=NULL; + jlong rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1clipboard_1read_1value_1finish_FUNC); + if (arg2) if ((lparg2 = (*env)->GetLongArrayElements(env, arg2, NULL)) == NULL) goto fail; + rc = (jlong)gdk_clipboard_read_value_finish((GdkClipboard*)arg0, (GAsyncResult *)arg1, (GError **)lparg2); +fail: + if (arg2 && lparg2) (*env)->ReleaseLongArrayElements(env, arg2, lparg2, 0); + GTK4_NATIVE_EXIT(env, that, gdk_1clipboard_1read_1value_1finish_FUNC); + return rc; +} +#endif + #ifndef NO_gdk_1clipboard_1set JNIEXPORT void JNICALL GTK4_NATIVE(gdk_1clipboard_1set) (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2) @@ -86,6 +157,132 @@ JNIEXPORT void JNICALL GTK4_NATIVE(gdk_1clipboard_1set_1text) } #endif +#ifndef NO_gdk_1content_1deserializer_1get_1cancellable +JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1content_1deserializer_1get_1cancellable) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1content_1deserializer_1get_1cancellable_FUNC); + rc = (jlong)gdk_content_deserializer_get_cancellable((GdkContentDeserializer*)arg0); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1deserializer_1get_1cancellable_FUNC); + return rc; +} +#endif + +#ifndef NO_gdk_1content_1deserializer_1get_1gtype +JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1content_1deserializer_1get_1gtype) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1content_1deserializer_1get_1gtype_FUNC); + rc = (jlong)gdk_content_deserializer_get_gtype((GdkContentDeserializer*)arg0); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1deserializer_1get_1gtype_FUNC); + return rc; +} +#endif + +#ifndef NO_gdk_1content_1deserializer_1get_1input_1stream +JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1content_1deserializer_1get_1input_1stream) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1content_1deserializer_1get_1input_1stream_FUNC); + rc = (jlong)gdk_content_deserializer_get_input_stream((GdkContentDeserializer*)arg0); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1deserializer_1get_1input_1stream_FUNC); + return rc; +} +#endif + +#ifndef NO_gdk_1content_1deserializer_1get_1mime_1type +JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1content_1deserializer_1get_1mime_1type) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1content_1deserializer_1get_1mime_1type_FUNC); + rc = (jlong)gdk_content_deserializer_get_mime_type((GdkContentDeserializer*)arg0); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1deserializer_1get_1mime_1type_FUNC); + return rc; +} +#endif + +#ifndef NO_gdk_1content_1deserializer_1get_1priority +JNIEXPORT jint JNICALL GTK4_NATIVE(gdk_1content_1deserializer_1get_1priority) + (JNIEnv *env, jclass that, jlong arg0) +{ + jint rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1content_1deserializer_1get_1priority_FUNC); + rc = (jint)gdk_content_deserializer_get_priority((GdkContentDeserializer*)arg0); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1deserializer_1get_1priority_FUNC); + return rc; +} +#endif + +#ifndef NO_gdk_1content_1deserializer_1get_1task_1data +JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1content_1deserializer_1get_1task_1data) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1content_1deserializer_1get_1task_1data_FUNC); + rc = (jlong)gdk_content_deserializer_get_task_data((GdkContentDeserializer*)arg0); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1deserializer_1get_1task_1data_FUNC); + return rc; +} +#endif + +#ifndef NO_gdk_1content_1deserializer_1get_1user_1data +JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1content_1deserializer_1get_1user_1data) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1content_1deserializer_1get_1user_1data_FUNC); + rc = (jlong)gdk_content_deserializer_get_user_data((GdkContentDeserializer*)arg0); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1deserializer_1get_1user_1data_FUNC); + return rc; +} +#endif + +#ifndef NO_gdk_1content_1deserializer_1get_1value +JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1content_1deserializer_1get_1value) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1content_1deserializer_1get_1value_FUNC); + rc = (jlong)gdk_content_deserializer_get_value((GdkContentDeserializer*)arg0); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1deserializer_1get_1value_FUNC); + return rc; +} +#endif + +#ifndef NO_gdk_1content_1deserializer_1return_1error +JNIEXPORT void JNICALL GTK4_NATIVE(gdk_1content_1deserializer_1return_1error) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1) +{ + GTK4_NATIVE_ENTER(env, that, gdk_1content_1deserializer_1return_1error_FUNC); + gdk_content_deserializer_return_error((GdkContentDeserializer*)arg0, (GError*)arg1); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1deserializer_1return_1error_FUNC); +} +#endif + +#ifndef NO_gdk_1content_1deserializer_1return_1success +JNIEXPORT void JNICALL GTK4_NATIVE(gdk_1content_1deserializer_1return_1success) + (JNIEnv *env, jclass that, jlong arg0) +{ + GTK4_NATIVE_ENTER(env, that, gdk_1content_1deserializer_1return_1success_FUNC); + gdk_content_deserializer_return_success((GdkContentDeserializer*)arg0); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1deserializer_1return_1success_FUNC); +} +#endif + +#ifndef NO_gdk_1content_1deserializer_1set_1task_1data +JNIEXPORT void JNICALL GTK4_NATIVE(gdk_1content_1deserializer_1set_1task_1data) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2) +{ + GTK4_NATIVE_ENTER(env, that, gdk_1content_1deserializer_1set_1task_1data_FUNC); + gdk_content_deserializer_set_task_data((GdkContentDeserializer*)arg0, (gpointer)arg1, (GDestroyNotify)arg2); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1deserializer_1set_1task_1data_FUNC); +} +#endif + #ifndef NO_gdk_1content_1formats_1builder_1add_1mime_1type JNIEXPORT void JNICALL GTK4_NATIVE(gdk_1content_1formats_1builder_1add_1mime_1type) (JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1) @@ -208,6 +405,160 @@ JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1content_1provider_1new_1union) } #endif +#ifndef NO_gdk_1content_1register_1deserializer +JNIEXPORT void JNICALL GTK4_NATIVE(gdk_1content_1register_1deserializer) + (JNIEnv *env, jclass that, jstring arg0, jlong arg1, jlong arg2, jlong arg3, jlong arg4) +{ + const char *lparg0= NULL; + GTK4_NATIVE_ENTER(env, that, gdk_1content_1register_1deserializer_FUNC); + if (arg0) if ((lparg0 = (*env)->GetStringUTFChars(env, arg0, NULL)) == NULL) goto fail; + gdk_content_register_deserializer((const char*)lparg0, (GType)arg1, (GdkContentDeserializeFunc)arg2, (gpointer)arg3, (GDestroyNotify)arg4); +fail: + if (arg0 && lparg0) (*env)->ReleaseStringUTFChars(env, arg0, lparg0); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1register_1deserializer_FUNC); +} +#endif + +#ifndef NO_gdk_1content_1register_1serializer +JNIEXPORT void JNICALL GTK4_NATIVE(gdk_1content_1register_1serializer) + (JNIEnv *env, jclass that, jlong arg0, jstring arg1, jlong arg2, jlong arg3, jlong arg4) +{ + const char *lparg1= NULL; + GTK4_NATIVE_ENTER(env, that, gdk_1content_1register_1serializer_FUNC); + if (arg1) if ((lparg1 = (*env)->GetStringUTFChars(env, arg1, NULL)) == NULL) goto fail; + gdk_content_register_serializer((GType)arg0, (const char*)lparg1, (GdkContentSerializeFunc)arg2, (gpointer)arg3, (GDestroyNotify)arg4); +fail: + if (arg1 && lparg1) (*env)->ReleaseStringUTFChars(env, arg1, lparg1); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1register_1serializer_FUNC); +} +#endif + +#ifndef NO_gdk_1content_1serializer_1get_1cancellable +JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1content_1serializer_1get_1cancellable) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1content_1serializer_1get_1cancellable_FUNC); + rc = (jlong)gdk_content_serializer_get_cancellable((GdkContentSerializer*)arg0); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1serializer_1get_1cancellable_FUNC); + return rc; +} +#endif + +#ifndef NO_gdk_1content_1serializer_1get_1gtype +JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1content_1serializer_1get_1gtype) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1content_1serializer_1get_1gtype_FUNC); + rc = (jlong)gdk_content_serializer_get_gtype((GdkContentSerializer*)arg0); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1serializer_1get_1gtype_FUNC); + return rc; +} +#endif + +#ifndef NO_gdk_1content_1serializer_1get_1mime_1type +JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1content_1serializer_1get_1mime_1type) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1content_1serializer_1get_1mime_1type_FUNC); + rc = (jlong)gdk_content_serializer_get_mime_type((GdkContentSerializer*)arg0); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1serializer_1get_1mime_1type_FUNC); + return rc; +} +#endif + +#ifndef NO_gdk_1content_1serializer_1get_1output_1stream +JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1content_1serializer_1get_1output_1stream) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1content_1serializer_1get_1output_1stream_FUNC); + rc = (jlong)gdk_content_serializer_get_output_stream((GdkContentSerializer*)arg0); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1serializer_1get_1output_1stream_FUNC); + return rc; +} +#endif + +#ifndef NO_gdk_1content_1serializer_1get_1priority +JNIEXPORT jint JNICALL GTK4_NATIVE(gdk_1content_1serializer_1get_1priority) + (JNIEnv *env, jclass that, jlong arg0) +{ + jint rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1content_1serializer_1get_1priority_FUNC); + rc = (jint)gdk_content_serializer_get_priority((GdkContentSerializer*)arg0); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1serializer_1get_1priority_FUNC); + return rc; +} +#endif + +#ifndef NO_gdk_1content_1serializer_1get_1task_1data +JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1content_1serializer_1get_1task_1data) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1content_1serializer_1get_1task_1data_FUNC); + rc = (jlong)gdk_content_serializer_get_task_data((GdkContentSerializer*)arg0); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1serializer_1get_1task_1data_FUNC); + return rc; +} +#endif + +#ifndef NO_gdk_1content_1serializer_1get_1user_1data +JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1content_1serializer_1get_1user_1data) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1content_1serializer_1get_1user_1data_FUNC); + rc = (jlong)gdk_content_serializer_get_user_data((GdkContentSerializer*)arg0); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1serializer_1get_1user_1data_FUNC); + return rc; +} +#endif + +#ifndef NO_gdk_1content_1serializer_1get_1value +JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1content_1serializer_1get_1value) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1content_1serializer_1get_1value_FUNC); + rc = (jlong)gdk_content_serializer_get_value((GdkContentSerializer*)arg0); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1serializer_1get_1value_FUNC); + return rc; +} +#endif + +#ifndef NO_gdk_1content_1serializer_1return_1error +JNIEXPORT void JNICALL GTK4_NATIVE(gdk_1content_1serializer_1return_1error) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1) +{ + GTK4_NATIVE_ENTER(env, that, gdk_1content_1serializer_1return_1error_FUNC); + gdk_content_serializer_return_error((GdkContentSerializer*)arg0, (GError*)arg1); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1serializer_1return_1error_FUNC); +} +#endif + +#ifndef NO_gdk_1content_1serializer_1return_1success +JNIEXPORT void JNICALL GTK4_NATIVE(gdk_1content_1serializer_1return_1success) + (JNIEnv *env, jclass that, jlong arg0) +{ + GTK4_NATIVE_ENTER(env, that, gdk_1content_1serializer_1return_1success_FUNC); + gdk_content_serializer_return_success((GdkContentSerializer*)arg0); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1serializer_1return_1success_FUNC); +} +#endif + +#ifndef NO_gdk_1content_1serializer_1set_1task_1data +JNIEXPORT void JNICALL GTK4_NATIVE(gdk_1content_1serializer_1set_1task_1data) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2) +{ + GTK4_NATIVE_ENTER(env, that, gdk_1content_1serializer_1set_1task_1data_FUNC); + gdk_content_serializer_set_task_data((GdkContentSerializer*)arg0, (gpointer)arg1, (GDestroyNotify)arg2); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1serializer_1set_1task_1data_FUNC); +} +#endif + #ifndef NO_gdk_1toplevel_1focus JNIEXPORT void JNICALL GTK4_NATIVE(gdk_1toplevel_1focus) (JNIEnv *env, jclass that, jlong arg0, jint arg1) diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4_stats.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4_stats.h index 39dc470cb09..4cd87e8840f 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4_stats.h +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4_stats.h @@ -22,9 +22,25 @@ typedef enum { gdk_1clipboard_1get_1content_FUNC, gdk_1clipboard_1get_1formats_FUNC, + gdk_1clipboard_1is_1local_FUNC, + gdk_1clipboard_1read_1async_FUNC, + gdk_1clipboard_1read_1finish_FUNC, + gdk_1clipboard_1read_1value_1async_FUNC, + gdk_1clipboard_1read_1value_1finish_FUNC, gdk_1clipboard_1set_FUNC, gdk_1clipboard_1set_1content_FUNC, gdk_1clipboard_1set_1text_FUNC, + gdk_1content_1deserializer_1get_1cancellable_FUNC, + gdk_1content_1deserializer_1get_1gtype_FUNC, + gdk_1content_1deserializer_1get_1input_1stream_FUNC, + gdk_1content_1deserializer_1get_1mime_1type_FUNC, + gdk_1content_1deserializer_1get_1priority_FUNC, + gdk_1content_1deserializer_1get_1task_1data_FUNC, + gdk_1content_1deserializer_1get_1user_1data_FUNC, + gdk_1content_1deserializer_1get_1value_FUNC, + gdk_1content_1deserializer_1return_1error_FUNC, + gdk_1content_1deserializer_1return_1success_FUNC, + gdk_1content_1deserializer_1set_1task_1data_FUNC, gdk_1content_1formats_1builder_1add_1mime_1type_FUNC, gdk_1content_1formats_1builder_1free_1to_1formats_FUNC, gdk_1content_1formats_1builder_1new_FUNC, @@ -34,6 +50,19 @@ typedef enum { gdk_1content_1provider_1new_1for_1value_FUNC, gdk_1content_1provider_1new_1typed_FUNC, gdk_1content_1provider_1new_1union_FUNC, + gdk_1content_1register_1deserializer_FUNC, + gdk_1content_1register_1serializer_FUNC, + gdk_1content_1serializer_1get_1cancellable_FUNC, + gdk_1content_1serializer_1get_1gtype_FUNC, + gdk_1content_1serializer_1get_1mime_1type_FUNC, + gdk_1content_1serializer_1get_1output_1stream_FUNC, + gdk_1content_1serializer_1get_1priority_FUNC, + gdk_1content_1serializer_1get_1task_1data_FUNC, + gdk_1content_1serializer_1get_1user_1data_FUNC, + gdk_1content_1serializer_1get_1value_FUNC, + gdk_1content_1serializer_1return_1error_FUNC, + gdk_1content_1serializer_1return_1success_FUNC, + gdk_1content_1serializer_1set_1task_1data_FUNC, gdk_1toplevel_1focus_FUNC, gdk_1toplevel_1get_1state_FUNC, gdk_1toplevel_1lower_FUNC, 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 57579f46e21..ae7076efac8 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 @@ -10079,6 +10079,18 @@ JNIEXPORT jint JNICALL OS_NATIVE(GValue_1sizeof) } #endif +#ifndef NO_G_1IS_1VALUE +JNIEXPORT jboolean JNICALL OS_NATIVE(G_1IS_1VALUE) + (JNIEnv *env, jclass that, jlong arg0) +{ + jboolean rc = 0; + OS_NATIVE_ENTER(env, that, G_1IS_1VALUE_FUNC); + rc = (jboolean)G_IS_VALUE(arg0); + OS_NATIVE_EXIT(env, that, G_1IS_1VALUE_FUNC); + return rc; +} +#endif + #ifndef NO_G_1OBJECT_1CLASS_1CONSTRUCTOR JNIEXPORT jlong JNICALL OS_NATIVE(G_1OBJECT_1CLASS_1CONSTRUCTOR) (JNIEnv *env, jclass that, jlong arg0) @@ -10233,6 +10245,18 @@ JNIEXPORT jlong JNICALL OS_NATIVE(G_1VALUE_1TYPE) } #endif +#ifndef NO_G_1VALUE_1TYPE_1NAME +JNIEXPORT jlong JNICALL OS_NATIVE(G_1VALUE_1TYPE_1NAME) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + OS_NATIVE_ENTER(env, that, G_1VALUE_1TYPE_1NAME_FUNC); + rc = (jlong)G_VALUE_TYPE_NAME(arg0); + OS_NATIVE_EXIT(env, that, G_1VALUE_1TYPE_1NAME_FUNC); + return rc; +} +#endif + #ifndef NO_PANGO_1PIXELS JNIEXPORT jint JNICALL OS_NATIVE(PANGO_1PIXELS) (JNIEnv *env, jclass that, jint arg0) @@ -11478,6 +11502,18 @@ JNIEXPORT jint JNICALL OS_NATIVE(g_1idle_1add) } #endif +#ifndef NO_g_1io_1error_1quark +JNIEXPORT jint JNICALL OS_NATIVE(g_1io_1error_1quark) + (JNIEnv *env, jclass that) +{ + jint rc = 0; + OS_NATIVE_ENTER(env, that, g_1io_1error_1quark_FUNC); + rc = (jint)g_io_error_quark(); + OS_NATIVE_EXIT(env, that, g_1io_1error_1quark_FUNC); + return rc; +} +#endif + #ifndef NO_g_1list_1append JNIEXPORT jlong JNICALL OS_NATIVE(g_1list_1append) (JNIEnv *env, jclass that, jlong arg0, jlong arg1) @@ -11794,6 +11830,78 @@ JNIEXPORT jlong JNICALL OS_NATIVE(g_1memory_1input_1stream_1new_1from_1data) } #endif +#ifndef NO_g_1memory_1output_1stream_1get_1data +JNIEXPORT jlong JNICALL OS_NATIVE(g_1memory_1output_1stream_1get_1data) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + OS_NATIVE_ENTER(env, that, g_1memory_1output_1stream_1get_1data_FUNC); + rc = (jlong)g_memory_output_stream_get_data((GMemoryOutputStream*)arg0); + OS_NATIVE_EXIT(env, that, g_1memory_1output_1stream_1get_1data_FUNC); + return rc; +} +#endif + +#ifndef NO_g_1memory_1output_1stream_1get_1data_1size +JNIEXPORT jlong JNICALL OS_NATIVE(g_1memory_1output_1stream_1get_1data_1size) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + OS_NATIVE_ENTER(env, that, g_1memory_1output_1stream_1get_1data_1size_FUNC); + rc = (jlong)g_memory_output_stream_get_data_size((GMemoryOutputStream*)arg0); + OS_NATIVE_EXIT(env, that, g_1memory_1output_1stream_1get_1data_1size_FUNC); + return rc; +} +#endif + +#ifndef NO_g_1memory_1output_1stream_1get_1size +JNIEXPORT jlong JNICALL OS_NATIVE(g_1memory_1output_1stream_1get_1size) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + OS_NATIVE_ENTER(env, that, g_1memory_1output_1stream_1get_1size_FUNC); + rc = (jlong)g_memory_output_stream_get_size((GMemoryOutputStream*)arg0); + OS_NATIVE_EXIT(env, that, g_1memory_1output_1stream_1get_1size_FUNC); + return rc; +} +#endif + +#ifndef NO_g_1memory_1output_1stream_1new_1resizable +JNIEXPORT jlong JNICALL OS_NATIVE(g_1memory_1output_1stream_1new_1resizable) + (JNIEnv *env, jclass that) +{ + jlong rc = 0; + OS_NATIVE_ENTER(env, that, g_1memory_1output_1stream_1new_1resizable_FUNC); + rc = (jlong)g_memory_output_stream_new_resizable(); + OS_NATIVE_EXIT(env, that, g_1memory_1output_1stream_1new_1resizable_FUNC); + return rc; +} +#endif + +#ifndef NO_g_1memory_1output_1stream_1steal_1as_1bytes +JNIEXPORT jlong JNICALL OS_NATIVE(g_1memory_1output_1stream_1steal_1as_1bytes) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + OS_NATIVE_ENTER(env, that, g_1memory_1output_1stream_1steal_1as_1bytes_FUNC); + rc = (jlong)g_memory_output_stream_steal_as_bytes((GMemoryOutputStream*)arg0); + OS_NATIVE_EXIT(env, that, g_1memory_1output_1stream_1steal_1as_1bytes_FUNC); + return rc; +} +#endif + +#ifndef NO_g_1memory_1output_1stream_1steal_1data +JNIEXPORT jlong JNICALL OS_NATIVE(g_1memory_1output_1stream_1steal_1data) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + OS_NATIVE_ENTER(env, that, g_1memory_1output_1stream_1steal_1data_FUNC); + rc = (jlong)g_memory_output_stream_steal_data((GMemoryOutputStream*)arg0); + OS_NATIVE_EXIT(env, that, g_1memory_1output_1stream_1steal_1data_FUNC); + return rc; +} +#endif + #ifndef NO_g_1menu_1insert_1item JNIEXPORT void JNICALL OS_NATIVE(g_1menu_1insert_1item) (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2) @@ -12124,6 +12232,80 @@ JNIEXPORT void JNICALL OS_NATIVE(g_1object_1unref) } #endif +#ifndef NO_g_1output_1stream_1splice_1async +JNIEXPORT void JNICALL OS_NATIVE(g_1output_1stream_1splice_1async) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jlong arg4, jlong arg5, jlong arg6) +{ + OS_NATIVE_ENTER(env, that, g_1output_1stream_1splice_1async_FUNC); + g_output_stream_splice_async((GOutputStream*)arg0, (GInputStream *)arg1, (GOutputStreamSpliceFlags)arg2, (int)arg3, (GCancellable *)arg4, (GAsyncReadyCallback)arg5, (gpointer)arg6); + OS_NATIVE_EXIT(env, that, g_1output_1stream_1splice_1async_FUNC); +} +#endif + +#ifndef NO_g_1output_1stream_1splice_1finish +JNIEXPORT jlong JNICALL OS_NATIVE(g_1output_1stream_1splice_1finish) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlongArray arg2) +{ + jlong *lparg2=NULL; + jlong rc = 0; + OS_NATIVE_ENTER(env, that, g_1output_1stream_1splice_1finish_FUNC); + if (arg2) if ((lparg2 = (*env)->GetLongArrayElements(env, arg2, NULL)) == NULL) goto fail; + rc = (jlong)g_output_stream_splice_finish((GOutputStream*)arg0, (GAsyncResult*)arg1, (GError**)lparg2); +fail: + if (arg2 && lparg2) (*env)->ReleaseLongArrayElements(env, arg2, lparg2, 0); + OS_NATIVE_EXIT(env, that, g_1output_1stream_1splice_1finish_FUNC); + return rc; +} +#endif + +#ifndef NO_g_1output_1stream_1write_1all +JNIEXPORT jboolean JNICALL OS_NATIVE(g_1output_1stream_1write_1all) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jlongArray arg3, jlong arg4, jlongArray arg5) +{ + jlong *lparg3=NULL; + jlong *lparg5=NULL; + jboolean rc = 0; + OS_NATIVE_ENTER(env, that, g_1output_1stream_1write_1all_FUNC); + if (arg3) if ((lparg3 = (*env)->GetLongArrayElements(env, arg3, NULL)) == NULL) goto fail; + if (arg5) if ((lparg5 = (*env)->GetLongArrayElements(env, arg5, NULL)) == NULL) goto fail; + rc = (jboolean)g_output_stream_write_all((GOutputStream*)arg0, (void*)arg1, (gsize)arg2, (gsize*)lparg3, (GCancellable*)arg4, (GError**)lparg5); +fail: + if (arg5 && lparg5) (*env)->ReleaseLongArrayElements(env, arg5, lparg5, 0); + if (arg3 && lparg3) (*env)->ReleaseLongArrayElements(env, arg3, lparg3, 0); + OS_NATIVE_EXIT(env, that, g_1output_1stream_1write_1all_FUNC); + return rc; +} +#endif + +#ifndef NO_g_1output_1stream_1write_1all_1async +JNIEXPORT void JNICALL OS_NATIVE(g_1output_1stream_1write_1all_1async) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jint arg3, jlong arg4, jlong arg5, jlong arg6) +{ + OS_NATIVE_ENTER(env, that, g_1output_1stream_1write_1all_1async_FUNC); + g_output_stream_write_all_async((GOutputStream*)arg0, (void*)arg1, (gsize)arg2, (int)arg3, (GCancellable*)arg4, (GAsyncReadyCallback)arg5, (gpointer)arg6); + OS_NATIVE_EXIT(env, that, g_1output_1stream_1write_1all_1async_FUNC); +} +#endif + +#ifndef NO_g_1output_1stream_1write_1all_1finish +JNIEXPORT jboolean JNICALL OS_NATIVE(g_1output_1stream_1write_1all_1finish) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlongArray arg2, jlongArray arg3) +{ + jlong *lparg2=NULL; + jlong *lparg3=NULL; + jboolean rc = 0; + OS_NATIVE_ENTER(env, that, g_1output_1stream_1write_1all_1finish_FUNC); + if (arg2) if ((lparg2 = (*env)->GetLongArrayElements(env, arg2, NULL)) == NULL) goto fail; + if (arg3) if ((lparg3 = (*env)->GetLongArrayElements(env, arg3, NULL)) == NULL) goto fail; + rc = (jboolean)g_output_stream_write_all_finish((GOutputStream*)arg0, (GAsyncResult*)arg1, (gsize*)lparg2, (GError**)lparg3); +fail: + if (arg3 && lparg3) (*env)->ReleaseLongArrayElements(env, arg3, lparg3, 0); + if (arg2 && lparg2) (*env)->ReleaseLongArrayElements(env, arg2, lparg2, 0); + OS_NATIVE_EXIT(env, that, g_1output_1stream_1write_1all_1finish_FUNC); + return rc; +} +#endif + #ifndef NO_g_1quark_1from_1string JNIEXPORT jint JNICALL OS_NATIVE(g_1quark_1from_1string) (JNIEnv *env, jclass that, jbyteArray arg0) @@ -12626,6 +12808,18 @@ JNIEXPORT jboolean JNICALL OS_NATIVE(g_1type_1is_1a) } #endif +#ifndef NO_g_1type_1name +JNIEXPORT jlong JNICALL OS_NATIVE(g_1type_1name) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + OS_NATIVE_ENTER(env, that, g_1type_1name_FUNC); + rc = (jlong)g_type_name((GType)arg0); + OS_NATIVE_EXIT(env, that, g_1type_1name_FUNC); + return rc; +} +#endif + #ifndef NO_g_1type_1parent JNIEXPORT jlong JNICALL OS_NATIVE(g_1type_1parent) (JNIEnv *env, jclass that, jlong arg0) @@ -12851,6 +13045,18 @@ JNIEXPORT jlong JNICALL OS_NATIVE(g_1utf8_1to_1utf16___3BJ_3J_3J_3J) } #endif +#ifndef NO_g_1value_1get_1boxed +JNIEXPORT jlong JNICALL OS_NATIVE(g_1value_1get_1boxed) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + OS_NATIVE_ENTER(env, that, g_1value_1get_1boxed_FUNC); + rc = (jlong)g_value_get_boxed((const GValue *)arg0); + OS_NATIVE_EXIT(env, that, g_1value_1get_1boxed_FUNC); + return rc; +} +#endif + #ifndef NO_g_1value_1get_1double JNIEXPORT jdouble JNICALL OS_NATIVE(g_1value_1get_1double) (JNIEnv *env, jclass that, jlong arg0) @@ -12875,6 +13081,18 @@ JNIEXPORT jfloat JNICALL OS_NATIVE(g_1value_1get_1float) } #endif +#ifndef NO_g_1value_1get_1gtype +JNIEXPORT jlong JNICALL OS_NATIVE(g_1value_1get_1gtype) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + OS_NATIVE_ENTER(env, that, g_1value_1get_1gtype_FUNC); + rc = (jlong)g_value_get_gtype((const GValue *)arg0); + OS_NATIVE_EXIT(env, that, g_1value_1get_1gtype_FUNC); + return rc; +} +#endif + #ifndef NO_g_1value_1get_1int JNIEXPORT jint JNICALL OS_NATIVE(g_1value_1get_1int) (JNIEnv *env, jclass that, jlong arg0) diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.c index 2b26e5a7ff7..e92dd85a90f 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.c +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.c @@ -2232,3 +2232,34 @@ swt_releaseArrayOfStringsUTF(JNIEnv *env, jobjectArray javaArray, char **cString } free(cStrings); } + +static void *string_boxed_copy(void *ptr) { + return ptr; +} + +static void string_boxed_free(void *ptr) { +} + +JNIEXPORT jlong JNICALL OS_NATIVE(register_1gtype_1for_1name) + (JNIEnv *env, jclass that, jstring name) +{ + long rc; + const char *lpname = NULL; + OS_NATIVE_ENTER(env, that, register_1gtype_1for_1name_FUNC) + if (name) lpname= (const char *) (*env)->GetStringUTFChars(env, name, NULL); + rc = g_boxed_type_register_static(lpname, string_boxed_copy, string_boxed_free); + if (name && lpname) (*env)->ReleaseStringUTFChars(env, name, lpname); + OS_NATIVE_EXIT(env, that, register_1gtype_1for_1name_FUNC) + return rc; +} + +JNIEXPORT jlong JNICALL OS_NATIVE(create_1gvalue) + (JNIEnv *env, jclass that, jlong gtype, jlong value) +{ + OS_NATIVE_ENTER(env, that, create_1gvalue_FUNC) + GValue *v = g_new0 (GValue, 1); + g_value_init(v, (GType)gtype); + g_value_take_boxed(v, (void *)value); + OS_NATIVE_EXIT(env, that, create_1gvalue_FUNC) + return (jlong)v; +} 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 a83c778d8ee..b83d217a8fe 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 @@ -824,6 +824,7 @@ typedef enum { GPollFD_1sizeof_FUNC, GTypeInfo_1sizeof_FUNC, GValue_1sizeof_FUNC, + G_1IS_1VALUE_FUNC, G_1OBJECT_1CLASS_1CONSTRUCTOR_FUNC, G_1OBJECT_1CLASS_1SET_1CONSTRUCTOR_FUNC, G_1OBJECT_1GET_1CLASS_FUNC, @@ -837,6 +838,7 @@ typedef enum { G_1TYPE_1LONG_FUNC, G_1TYPE_1STRING_FUNC, G_1VALUE_1TYPE_FUNC, + G_1VALUE_1TYPE_1NAME_FUNC, PANGO_1PIXELS_FUNC, PANGO_1TYPE_1FONT_1DESCRIPTION_FUNC, PANGO_1TYPE_1FONT_1FACE_FUNC, @@ -870,6 +872,7 @@ typedef enum { call__JJJJJ_FUNC, call__JJJJJJJ_FUNC, call__JJJJJJJJ_FUNC, + create_1gvalue_FUNC, g_1action_1get_1enabled_FUNC, g_1action_1get_1state_FUNC, g_1action_1map_1add_1action_FUNC, @@ -928,6 +931,7 @@ typedef enum { g_1icon_1new_1for_1string_FUNC, g_1icon_1to_1string_FUNC, g_1idle_1add_FUNC, + g_1io_1error_1quark_FUNC, g_1list_1append_FUNC, g_1list_1data_FUNC, g_1list_1free_FUNC, @@ -954,6 +958,12 @@ typedef enum { g_1main_1context_1wakeup_FUNC, g_1malloc_FUNC, g_1memory_1input_1stream_1new_1from_1data_FUNC, + g_1memory_1output_1stream_1get_1data_FUNC, + g_1memory_1output_1stream_1get_1data_1size_FUNC, + g_1memory_1output_1stream_1get_1size_FUNC, + g_1memory_1output_1stream_1new_1resizable_FUNC, + g_1memory_1output_1stream_1steal_1as_1bytes_FUNC, + g_1memory_1output_1stream_1steal_1data_FUNC, g_1menu_1insert_1item_FUNC, g_1menu_1item_1new_FUNC, g_1menu_1item_1new_1section_FUNC, @@ -978,6 +988,11 @@ typedef enum { g_1object_1set__J_3B_3BJ_FUNC, g_1object_1set_1qdata_FUNC, g_1object_1unref_FUNC, + g_1output_1stream_1splice_1async_FUNC, + g_1output_1stream_1splice_1finish_FUNC, + g_1output_1stream_1write_1all_FUNC, + g_1output_1stream_1write_1all_1async_FUNC, + g_1output_1stream_1write_1all_1finish_FUNC, g_1quark_1from_1string_FUNC, g_1set_1prgname_FUNC, g_1signal_1add_1emission_1hook_FUNC, @@ -1017,6 +1032,7 @@ typedef enum { g_1type_1class_1unref_FUNC, g_1type_1interface_1peek_1parent_FUNC, g_1type_1is_1a_FUNC, + g_1type_1name_FUNC, g_1type_1parent_FUNC, g_1type_1register_1static_FUNC, g_1unsetenv_FUNC, @@ -1031,8 +1047,10 @@ typedef enum { g_1utf8_1strlen_FUNC, g_1utf8_1to_1utf16__JJ_3J_3J_3J_FUNC, g_1utf8_1to_1utf16___3BJ_3J_3J_3J_FUNC, + g_1value_1get_1boxed_FUNC, g_1value_1get_1double_FUNC, g_1value_1get_1float_FUNC, + g_1value_1get_1gtype_FUNC, g_1value_1get_1int_FUNC, g_1value_1get_1int64_FUNC, g_1value_1get_1object_FUNC, @@ -1203,6 +1221,7 @@ typedef enum { pango_1version_FUNC, printerOptionWidgetNewProc_1CALLBACK_FUNC, realpath_FUNC, + register_1gtype_1for_1name_FUNC, strcmp_FUNC, swt_1debug_1on_1fatal_1warnings_FUNC, swt_1fixed_1accessible_1get_1type_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 c319bbac70b..2731e4e83bb 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 @@ -155,7 +155,85 @@ public static String getEnvironmentalVariable (String envVarName) { } /** Constants */ + /* enum GFileError */ + public static final int G_FILE_ERROR_EXIST = 0; + public static final int G_FILE_ERROR_ISDIR = 1; + public static final int G_FILE_ERROR_ACCES = 2; + public static final int G_FILE_ERROR_NAMETOOLONG = 3; + public static final int G_FILE_ERROR_NOENT = 4; + public static final int G_FILE_ERROR_NOTDIR = 5; + public static final int G_FILE_ERROR_NXIO = 6; + public static final int G_FILE_ERROR_NODEV = 7; + public static final int G_FILE_ERROR_ROFS = 8; + public static final int G_FILE_ERROR_TXTBSY = 9; + public static final int G_FILE_ERROR_FAULT = 10; + public static final int G_FILE_ERROR_LOOP = 11; + public static final int G_FILE_ERROR_NOSPC = 12; + public static final int G_FILE_ERROR_NOMEM = 13; + public static final int G_FILE_ERROR_MFILE = 14; + public static final int G_FILE_ERROR_NFILE = 15; + public static final int G_FILE_ERROR_BADF = 16; + public static final int G_FILE_ERROR_INVAL = 17; + public static final int G_FILE_ERROR_PIPE = 18; + public static final int G_FILE_ERROR_AGAIN = 19; + public static final int G_FILE_ERROR_INTR = 20; public static final int G_FILE_ERROR_IO = 21; + public static final int G_FILE_ERROR_PERM = 22; + public static final int G_FILE_ERROR_NOSYS = 23; + public static final int G_FILE_ERROR_FAILED = 24; + + /* enum GIOErrorEnum */ + public static final int G_IO_ERROR_FAILED = 0; + public static final int G_IO_ERROR_NOT_FOUND = 1; + public static final int G_IO_ERROR_EXISTS = 2; + public static final int G_IO_ERROR_IS_DIRECTORY = 3; + public static final int G_IO_ERROR_NOT_DIRECTORY = 4; + public static final int G_IO_ERROR_NOT_EMPTY = 5; + public static final int G_IO_ERROR_NOT_REGULAR_FILE = 6; + public static final int G_IO_ERROR_NOT_SYMBOLIC_LINK = 7; + public static final int G_IO_ERROR_NOT_MOUNTABLE_FILE = 8; + public static final int G_IO_ERROR_FILENAME_TOO_LONG = 9; + public static final int G_IO_ERROR_INVALID_FILENAME = 10; + public static final int G_IO_ERROR_TOO_MANY_LINKS = 11; + public static final int G_IO_ERROR_NO_SPACE = 12; + public static final int G_IO_ERROR_INVALID_ARGUMENT = 13; + public static final int G_IO_ERROR_PERMISSION_DENIED = 14; + public static final int G_IO_ERROR_NOT_SUPPORTED = 15; + public static final int G_IO_ERROR_NOT_MOUNTED = 16; + public static final int G_IO_ERROR_ALREADY_MOUNTED = 17; + public static final int G_IO_ERROR_CLOSED = 18; + public static final int G_IO_ERROR_CANCELLED = 19; + public static final int G_IO_ERROR_PENDING = 20; + public static final int G_IO_ERROR_READ_ONLY = 21; + public static final int G_IO_ERROR_CANT_CREATE_BACKUP = 22; + public static final int G_IO_ERROR_WRONG_ETAG = 23; + public static final int G_IO_ERROR_TIMED_OUT = 24; + public static final int G_IO_ERROR_WOULD_RECURSE = 25; + public static final int G_IO_ERROR_BUSY = 26; + public static final int G_IO_ERROR_WOULD_BLOCK = 27; + public static final int G_IO_ERROR_HOST_NOT_FOUND = 28; + public static final int G_IO_ERROR_WOULD_MERGE = 29; + public static final int G_IO_ERROR_FAILED_HANDLED = 30; + public static final int G_IO_ERROR_TOO_MANY_OPEN_FILES = 31; + public static final int G_IO_ERROR_NOT_INITIALIZED = 32; + public static final int G_IO_ERROR_ADDRESS_IN_USE = 33; + public static final int G_IO_ERROR_PARTIAL_INPUT = 34; + public static final int G_IO_ERROR_INVALID_DATA = 35; + public static final int G_IO_ERROR_DBUS_ERROR = 36; + public static final int G_IO_ERROR_HOST_UNREACHABLE = 37; + public static final int G_IO_ERROR_NETWORK_UNREACHABLE = 38; + public static final int G_IO_ERROR_CONNECTION_REFUSED = 39; + public static final int G_IO_ERROR_PROXY_FAILED = 40; + public static final int G_IO_ERROR_PROXY_AUTH_FAILED = 41; + public static final int G_IO_ERROR_PROXY_NEED_AUTH = 42; + public static final int G_IO_ERROR_PROXY_NOT_ALLOWED = 43; + public static final int G_IO_ERROR_BROKEN_PIPE = 44; + public static final int G_IO_ERROR_CONNECTION_CLOSED = G_IO_ERROR_BROKEN_PIPE; + public static final int G_IO_ERROR_NOT_CONNECTED = 45; + public static final int G_IO_ERROR_MESSAGE_TOO_LARGE = 46; + public static final int G_IO_ERROR_NO_SUCH_DEVICE = 47; + public static final int G_IO_ERROR_DESTINATION_UNSET = 48; + public static final int G_FILE_TEST_IS_DIR = 1 << 2; public static final int G_FILE_TEST_IS_EXECUTABLE = 1 << 3; public static final int G_SIGNAL_MATCH_DATA = 1 << 4; @@ -165,6 +243,10 @@ public static String getEnvironmentalVariable (String envVarName) { public static final int G_LOG_LEVEL_MASK = 0xfffffffc; public static final int G_APP_INFO_CREATE_NONE = 0; public static final int G_APP_INFO_CREATE_SUPPORTS_URIS = (1 << 1); + public static final int G_OUTPUT_STREAM_SPLICE_NONE = 0; + public static final int G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE = (1 << 0); + public static final int G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET = (1 << 1); + public static final int G_PRIORITY_DEFAULT = 0; public static final int GTK_TYPE_TEXT_BUFFER = 21; public static final int PANGO_ALIGN_LEFT = 0; public static final int PANGO_ALIGN_CENTER = 1; @@ -567,6 +649,33 @@ public static String getEnvironmentalVariable (String envVarName) { /* custom version of g_utf8 for 16 bit */ public static final native long g_utf16_offset_to_utf8_offset(long str, long offset); + /** + * Creates a GType for the given name. The name must be unique for the lifetime + * of the process. + * + * This gives a unique GType to register in GTK4's serializers. + * + * @param name The name of the type - must be unique + * @return the new GType - the data is owned by GTK and must not be freed + * @method flags=no_gen + * @category custom + */ + // TODO this is too generic a name - this method is only for use with ContentProvider + public static final native long register_gtype_for_name(String name); + + /** + * Creates a GValue for the given GType, when that GType was created by + * {@link #register_gtype_for_name(String)} + * + * @param gtype the type created with {@link #register_gtype_for_name(String)} + * @param value a non-zero value to store in the gvalue of type gtype + * @return the new GValue - the data is owned by the caller of the method + * @method flags=no_gen + * @category custom + */ + // TODO this is too generic a name - this method is only for use with ContentProvider + public static final native long create_gvalue(long gtype, long value); + /** CUSTOM_CODE END */ /** @@ -847,6 +956,8 @@ public static boolean isX11 () { /** @method flags=const */ public static final native long G_TYPE_INT64(); public static final native long G_VALUE_TYPE(long value); +public static final native long G_VALUE_TYPE_NAME(long value); +public static final native boolean G_IS_VALUE(long value); public static final native long G_OBJECT_TYPE(long instance); /** @method flags=const */ public static final native long G_TYPE_STRING(); @@ -932,6 +1043,7 @@ public static boolean isX11 () { */ public static final native boolean g_content_type_is_a(long type, byte[] supertype); public static final native int g_file_error_quark(); +public static final native int g_io_error_quark(); /** * @param info cast=(GFileInfo *) */ @@ -1332,6 +1444,11 @@ public static boolean isX11 () { public static final native void g_type_class_unref(long g_class); /** @param iface cast=(gpointer) */ public static final native long g_type_interface_peek_parent(long iface); +/** + * @param g_type cast=(GType) + * @return char * that must be freed + */ +public static final native long g_type_name(long g_type); /** * @param type cast=(GType) * @param is_a_type cast=(GType) @@ -1410,6 +1527,11 @@ public static boolean isX11 () { public static final native void g_value_unset (long value); /** @param value cast=(const GValue *) */ public static final native long g_value_peek_pointer(long value); +/** @param value cast=(const GValue *) */ +public static final native long g_value_get_boxed(long value); +/** @param value cast=(const GValue *) */ +public static final native long g_value_get_gtype(long value); + /** * @param variable cast=(const gchar *),flags=no_out */ @@ -2331,4 +2453,71 @@ public static final native long g_dbus_proxy_new_for_bus_sync(int bus_type, int */ public static final native long g_memory_input_stream_new_from_data(long data, long len, long destroy); +/** + * @param stream cast=(GOutputStream*) + * @param source cast=(GInputStream *) + * @param flags cast=(GOutputStreamSpliceFlags) + * @param io_priority cast=(int) + * @param cancellable cast=(GCancellable *) + * @param callback cast=(GAsyncReadyCallback) + * @param user_data cast=(gpointer) + */ +public static final native void g_output_stream_splice_async(long stream, long source, int flags, int io_priority, long cancellable, long callback, long user_data); +/** + * @param stream cast=(GOutputStream*) + * @param result cast=(GAsyncResult*) + * @param error cast=(GError**) + */ +public static final native long g_output_stream_splice_finish(long stream, long result, long[] error); +/** + * + */ +public static final native long g_memory_output_stream_new_resizable(); +/** + * @param ostream cast=(GMemoryOutputStream*) + */ +public static final native long g_memory_output_stream_get_data(long ostream); +/** + * @param ostream cast=(GMemoryOutputStream*) + */ +public static final native long g_memory_output_stream_get_size(long ostream); +/** + * @param ostream cast=(GMemoryOutputStream*) + */ +public static final native long g_memory_output_stream_get_data_size(long ostream); +/** + * @param ostream cast=(GMemoryOutputStream*) + */ +public static final native long g_memory_output_stream_steal_data(long ostream); +/** + * @param ostream cast=(GMemoryOutputStream*) + */ +public static final native long g_memory_output_stream_steal_as_bytes(long ostream); +/** + * @param stream cast=(GOutputStream*) + * @param buffer cast=(void*) + * @param count cast=(gsize) + * @param bytes_written cast=(gsize*) + * @param cancellable cast=(GCancellable*) + * @param error cast=(GError**) + */ +public static final native boolean g_output_stream_write_all(long stream, long buffer, long count, long[] bytes_written, long cancellable, long[] error); +/** + * @param stream cast=(GOutputStream*) + * @param buffer cast=(void*) + * @param count cast=(gsize) + * @param io_priority cast=(int) + * @param cancellable cast=(GCancellable*) + * @param callback cast=(GAsyncReadyCallback) + * @param user_data cast=(gpointer) + */ +public static final native void g_output_stream_write_all_async(long stream, long buffer, long count, int io_priority, long cancellable, long callback, long user_data); +/** + * + * @param stream cast=(GOutputStream*) + * @param result cast=(GAsyncResult*) + * @param bytes_written cast=(gsize*) + * @param error cast=(GError**) + */ +public static final native boolean g_output_stream_write_all_finish(long stream, long result, long[] bytes_written, long[] error); } diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk4/GTK4.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk4/GTK4.java index 48ceb120d5c..6fb27115481 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk4/GTK4.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk4/GTK4.java @@ -838,6 +838,42 @@ public class GTK4 { * @param clipboard cast=(GdkClipboard*) */ public static final native long gdk_clipboard_get_content(long clipboard); + /** + * @param clipboard cast=(GdkClipboard*) + * @param type cast=(GType) + * @param io_priority cast=(int) + * @param cancellable cast=(GCancellable *) + * @param callback cast=(GAsyncReadyCallback) + * @param user_data cast=(gpointer) + */ + public static final native void gdk_clipboard_read_value_async(long clipboard, long type, int io_priority, long cancellable, long callback, long user_data); + /** + * @param clipboard cast=(GdkClipboard*) + * @param result cast=(GAsyncResult *) + * @param error cast=(GError **) + */ + public static final native long gdk_clipboard_read_value_finish(long clipboard, long result, long[] error); + /** + * @param clipboard cast=(GdkClipboard*) + * @param mime_types cast=(const char **) + * @param io_priority cast=(int) + * @param cancellable cast=(GCancellable *) + * @param callback cast=(GAsyncReadyCallback) + * @param user_data cast=(gpointer) + */ + public static final native void gdk_clipboard_read_async(long clipboard, String[] mime_types, int io_priority, long cancellable, long callback, long user_data); + /** + * @param clipboard cast=(GdkClipboard*) + * @param result cast=(GAsyncResult *) + * @param out_mime_type cast=(const char**) + * @param error cast=(GError **) + */ + public static final native long gdk_clipboard_read_finish(long clipboard, long result, long[] out_mime_type, long[] error); + /** + * @param clipboard cast=(GdkClipboard*) + */ + public static final native boolean gdk_clipboard_is_local(long clipboard); + /** * @param provider cast=(GdkContentProvider *) * @param value cast=(GValue *) @@ -865,6 +901,118 @@ public class GTK4 { */ public static final native long gdk_content_formats_get_gtypes(long formats, long[] n_gtypes); + /** + * @param type cast=(GType) + * @param mime_type cast=(const char*) + * @param serialize cast=(GdkContentSerializeFunc) + * @param data cast=(gpointer) + * @param notify cast=(GDestroyNotify) + */ + public static final native void gdk_content_register_serializer(long type, String mime_type, long serialize, long data, long notify); + /** + * @param serializer cast=(GdkContentSerializer*) + */ + public static final native long gdk_content_serializer_get_cancellable(long serializer); + /** + * @param serializer cast=(GdkContentSerializer*) + */ + public static final native long gdk_content_serializer_get_gtype(long serializer); + /** + * @param serializer cast=(GdkContentSerializer*) + */ + public static final native long gdk_content_serializer_get_mime_type(long serializer); + /** + * @param serializer cast=(GdkContentSerializer*) + */ + public static final native long gdk_content_serializer_get_output_stream(long serializer); + /** + * @param serializer cast=(GdkContentSerializer*) + */ + public static final native int gdk_content_serializer_get_priority(long serializer); + /** + * @param serializer cast=(GdkContentSerializer*) + */ + public static final native long gdk_content_serializer_get_task_data(long serializer); + /** + * @param serializer cast=(GdkContentSerializer*) + */ + public static final native long gdk_content_serializer_get_user_data(long serializer); + /** + * @param serializer cast=(GdkContentSerializer*) + */ + public static final native long gdk_content_serializer_get_value(long serializer); + /** + * @param serializer cast=(GdkContentSerializer*) + * @param error cast=(GError*) + */ + public static final native void gdk_content_serializer_return_error(long serializer, long error); + /** + * @param serializer cast=(GdkContentSerializer*) + */ + public static final native void gdk_content_serializer_return_success(long serializer); + /** + * @param serializer cast=(GdkContentSerializer*) + * @param data cast=(gpointer) + * @param notify cast=(GDestroyNotify) + */ + public static final native void gdk_content_serializer_set_task_data(long serializer, long data, long notify); + /** + * @param mime_type cast=(const char*) + * @param type cast=(GType) + * @param deserialize cast=(GdkContentDeserializeFunc) + * @param data cast=(gpointer) + * @param notify cast=(GDestroyNotify) + */ + public static final native void gdk_content_register_deserializer(String mime_type, long type, long deserialize, long data, long notify); + /** + * @param deserializer cast=(GdkContentDeserializer*) + */ + public static final native long gdk_content_deserializer_get_cancellable(long deserializer); + /** + * @param deserializer cast=(GdkContentDeserializer*) + */ + public static final native long gdk_content_deserializer_get_gtype(long deserializer); + /** + * @param deserializer cast=(GdkContentDeserializer*) + */ + public static final native long gdk_content_deserializer_get_input_stream(long deserializer); + /** + * @param deserializer cast=(GdkContentDeserializer*) + */ + public static final native long gdk_content_deserializer_get_mime_type(long deserializer); + /** + * @param deserializer cast=(GdkContentDeserializer*) + */ + public static final native int gdk_content_deserializer_get_priority(long deserializer); + /** + * @param deserializer cast=(GdkContentDeserializer*) + */ + public static final native long gdk_content_deserializer_get_task_data(long deserializer); + /** + * @param deserializer cast=(GdkContentDeserializer*) + */ + public static final native long gdk_content_deserializer_get_user_data(long deserializer); + /** + * @param deserializer cast=(GdkContentDeserializer*) + */ + public static final native long gdk_content_deserializer_get_value(long deserializer); + /** + * @param deserializer cast=(GdkContentDeserializer*) + * @param error cast=(GError*) + */ + public static final native void gdk_content_deserializer_return_error(long deserializer, long error); + /** + * @param deserializer cast=(GdkContentDeserializer*) + */ + public static final native void gdk_content_deserializer_return_success(long deserializer); + /** + * @param deserializer cast=(GdkContentDeserializer*) + * @param data cast=(gpointer) + * @param notify cast=(GDestroyNotify) + */ + public static final native void gdk_content_deserializer_set_task_data(long deserializer, long data, long notify); + + public static final native long gtk_gesture_rotate_new(); public static final native long gtk_gesture_zoom_new(); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/AsyncFinishUtil.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/AsyncFinishUtil.java new file mode 100644 index 00000000000..eb6ef6c9adf --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/AsyncFinishUtil.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2020, 2025 Red Hat Inc. and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.swt.internal; + +import java.lang.reflect.*; +import java.util.function.*; + +import org.eclipse.swt.widgets.*; + +/** + * This class is an internal class based on {@link SyncDialogUtil} for the + * non-UI and reentrant parts of GTK4, such as the clipboard. + * + * The run method is non-blocking here! + */ + +public class AsyncFinishUtil { + private Callback dialogResponseCallback; + private Function dialogAsyncFinish; + private Long dialogAsyncValue; + + /** + * TODO: Write new javadoc here + */ + public void run(Display display, AsyncReadyCallback callback) { + initializeResponseCallback(); + + dialogAsyncFinish = callback::await; + callback.async(dialogResponseCallback.getAddress()); + } + + /** + * Returns null until await (aka finish) method is called. + * Once await is finished, will have non-null return value from finish method + */ + public Long getDialogAsyncValue() { + return dialogAsyncValue; + } + + /** + * Initializes the response callback and resets the responseID of the dialog to + * the default value. This function should be called before connect the dialog + * to the "response" signal, as this sets up the callback. + */ + private void initializeResponseCallback() { + dialogResponseCallback = new Callback(this, "dialogResponseProc", void.class, + new Type[] { long.class, long.class, long.class }); + dialogAsyncValue = null; + } + + private void disposeResponseCallback() { + dialogResponseCallback.dispose(); + dialogResponseCallback = null; + dialogAsyncFinish = null; + } + + void dialogResponseProc(long dialog, long response, long user_data) { + if (dialogAsyncFinish != null) { + dialogAsyncValue = dialogAsyncFinish.apply(response); + } + disposeResponseCallback(); + } +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/SyncFinishCallback.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/SyncFinishCallback.java new file mode 100644 index 00000000000..fd4b56e508d --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/SyncFinishCallback.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2024 Patrick Ziegler and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Patrick Ziegler - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.internal; + +/** + * This class implements the GIO AsyncReadyCallback type and is used to + * transform an asynchronous {@code async} and synchronous {@code await} + * operation into a single synchronous {@code run} operation. + */ +public interface SyncFinishCallback { + /** + * This method is responsible for initializes the asynchronous operation + * + * @param callback The callback address to execute when the operation is + * complete. + */ + void async(long callback); + + /** + * This method is called from within the callback function in order to + * finish the executed operation and to return the result. + * + * @param result The generic, asynchronous function result. + * @return The specific result of the operation. + */ + T await(long result); +} \ No newline at end of file diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/SyncFinishUtil.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/SyncFinishUtil.java new file mode 100644 index 00000000000..f069ef32c53 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/SyncFinishUtil.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2020, 2025 Red Hat Inc. and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.swt.internal; + +import java.lang.reflect.*; +import java.util.function.*; + +import org.eclipse.swt.widgets.*; + +/** + * This class is an internal class based on {@link SyncDialogUtil} for the + * non-UI and reentrant parts of GTK4, such as the clipboard. + * + * TODO should "org.eclipse.swt.internal.gtk.dispatchEvent" be set on display so + * that (very?) unrelated events aren't processed until we are done here? We + * need to process some unrelated events because one async operation could be + * writing to a stream another is reading from and they both need to run + * "simultaneously" for the operation to succeed. + */ + +public class SyncFinishUtil { + private Callback dialogResponseCallback; + private Function dialogAsyncFinish; + private T dialogAsyncValue; + private boolean dialogAsyncValueSet; + + /** + * This method implements the {@code AsyncReadyCallback} mechanism that is used + * in GTK4. Most operations within GTK4 are executed asynchronously, where the + * user is given the option to respond to the completion of such an operation + * via a callback method, in order to e.g. process the result or to apply + * additional cleanup tasks.
+ * When calling this method, the asynchronous operation is initiated via the + * {code asyncOpen} parameter. Callers have to ensure that the callback address + * is used as argument for the {@code AsyncReadyCallback} parameter. From within + * the callback routine, the {@code asyncFinish} function is called, receiving + * the {@code AsyncResult} of the callback as argument and returning the + * {@code long} value of the callback function.
+ * This method blocks until the callback method has been called. It is therefore + * essential that callers use the address of the {@link Callback} as address for + * the {@code AsyncReadyCallback} object. + */ + public T run(Display display, SyncFinishCallback callback) { + System.out.println("Running SyncFinishUtil " + this.hashCode()); + initializeResponseCallback(); + + dialogAsyncFinish = callback::await; + System.out.println("Running SyncFinishUtil await " + this.hashCode()); + callback.async(dialogResponseCallback.getAddress()); + + System.out.println("Running SyncFinishUtil readAndDispatch " + this.hashCode()); + while (!display.isDisposed()) { + if (dialogAsyncValueSet) { + break; + } + display.readAndDispatch(); + } + + disposeResponseCallback(); + System.out.println("Running SyncFinishUtil FINISHED " + this.hashCode()); + return dialogAsyncValue; + } + + /** + * Initializes the response callback and resets the responseID of the dialog to + * the default value. This function should be called before connect the dialog + * to the "response" signal, as this sets up the callback. + */ + private void initializeResponseCallback() { + dialogResponseCallback = new Callback(this, "dialogResponseProc", void.class, + new Type[] { long.class, long.class, long.class }); + dialogAsyncValue = null; + dialogAsyncValueSet = false; + } + + private void disposeResponseCallback() { + dialogResponseCallback.dispose(); + dialogResponseCallback = null; + dialogAsyncFinish = null; + } + + /** + * Callback function for the "response" signal in GtkDialog widgets. + * Responsibility of destroying the dialog is the owner of the dialog handle. + * + * Note: Native dialogs are platform dialogs that don't use GtkDialog or + * GtkWindow. + */ + void dialogResponseProc(long dialog, long response, long user_data) { + System.out.println("Running SyncFinishUtil dialogResponseProc " + this.hashCode()); + if (dialogAsyncFinish != null) { + System.out.println("Running SyncFinishUtil apply " + this.hashCode()); + dialogAsyncValue = dialogAsyncFinish.apply(response); + System.out.println("Running SyncFinishUtil dialogAsyncValueSet " + this.hashCode()); + dialogAsyncValueSet = true; + } + } +} diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/ClipboardSwingTester.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/ClipboardSwingTester.java new file mode 100644 index 00000000000..7d6478c7830 --- /dev/null +++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/ClipboardSwingTester.java @@ -0,0 +1,10 @@ +package org.eclipse.swt.tests.junit; + +public class ClipboardSwingTester { + + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + +} diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_dnd_Clipboard.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_dnd_Clipboard.java index 0cbdcd8a667..afdf6e51258 100644 --- a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_dnd_Clipboard.java +++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_dnd_Clipboard.java @@ -15,6 +15,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeTrue; import java.io.BufferedReader; @@ -57,7 +58,7 @@ public class Test_org_eclipse_swt_dnd_Clipboard { private static final int DEFAULT_TIMEOUT_MS = 10000; - static int uniqueId = 1; + private static int uniqueId = 1; private Display display; private Shell shell; private Clipboard clipboard; @@ -79,18 +80,6 @@ public void setUp() { rtfTransfer = RTFTransfer.getInstance(); } - private void sleep() throws InterruptedException { - if (SwtTestUtil.isGTK4) { - /** - * TODO remove all uses of sleep and change them to processEvents with the - * suitable conditional, or entirely remove them - */ - SwtTestUtil.processEvents(100, null); - } else { - SwtTestUtil.processEvents(); - } - } - /** * Note: Wayland backend does not allow access to system clipboard from * non-focussed windows. So we have to create/open and focus a window here so @@ -100,7 +89,12 @@ private void openAndFocusShell() throws InterruptedException { shell = new Shell(display); shell.open(); shell.setFocus(); - sleep(); + // A single "processEvents" iteration is insufficient, therefore we run for + // 100ms. + // As best as I can tell, once window manager gets focus (at least on wayland) + // additional events can arrive that need to be processed before the clipboard + // contents can be set. + SwtTestUtil.processEvents(100, null); } /** @@ -112,12 +106,10 @@ private void openAndFocusRemote() throws Exception { startRemoteClipboardCommands(); remote.setFocus(); remote.waitUntilReady(); - sleep(); } @AfterEach public void tearDown() throws Exception { - sleep(); try { stopRemoteClipboardCommands(); } finally { @@ -337,14 +329,13 @@ public void test_LocalClipboard() throws Exception { assertEquals(helloWorldRtf, clipboard.getContents(rtfTransfer)); } - @Test + @RepeatedTest(value = 5) public void test_setContents() throws Exception { try { openAndFocusShell(); String helloWorld = getUniqueTestString(); clipboard.setContents(new Object[] { helloWorld }, new Transfer[] { textTransfer }); - sleep(); openAndFocusRemote(); SwtTestUtil.processEvents(1000, () -> helloWorld.equals(runOperationInThread(remote::getStringContents))); @@ -352,9 +343,12 @@ public void test_setContents() throws Exception { assertEquals(helloWorld, result); } catch (Exception | AssertionError e) { if (SwtTestUtil.isGTK4 && !SwtTestUtil.isX11) { - // TODO make the code + test stable - throw new RuntimeException( - "This test is really unstable on wayland backend, at least with Ubuntu 25.04", e); + // If this fails consistently + fail(""" + Wayland + GTK probably didn't know that the the shell had sufficient focus to copy to clipboard. + Consider increasing how long processEvents is run for in openAndFocusShell + """, + e); } throw e; } diff --git a/tests/org.eclipse.swt.tests/data/clipboard/ClipboardCommandsImpl.java b/tests/org.eclipse.swt.tests/data/clipboard/ClipboardCommandsImpl.java index 28123f10fa6..d88b436fe25 100644 --- a/tests/org.eclipse.swt.tests/data/clipboard/ClipboardCommandsImpl.java +++ b/tests/org.eclipse.swt.tests/data/clipboard/ClipboardCommandsImpl.java @@ -102,4 +102,4 @@ private void invokeAndWait(Runnable run) throws RemoteException { } } -} \ No newline at end of file +}