diff --git a/bundles/org.eclipse.swt.tools/JNI Generation/org/eclipse/swt/tools/internal/ASTType.java b/bundles/org.eclipse.swt.tools/JNI Generation/org/eclipse/swt/tools/internal/ASTType.java
index 1c9cfd55d4e..538e81ea1ed 100644
--- a/bundles/org.eclipse.swt.tools/JNI Generation/org/eclipse/swt/tools/internal/ASTType.java
+++ b/bundles/org.eclipse.swt.tools/JNI Generation/org/eclipse/swt/tools/internal/ASTType.java
@@ -148,7 +148,10 @@ public String getTypeSignature2() {
if (name.equals("Ljava/lang/String;")) return "jstring";
if (name.equals("Ljava/lang/Class;")) return "jclass";
if (isArray()) {
- return getComponentType().getTypeSignature2() + "Array";
+ if (getComponentType().isPrimitive()) {
+ return getComponentType().getTypeSignature2() + "Array";
+ }
+ return "jobjectArray";
}
return "jobject";
}
diff --git a/bundles/org.eclipse.swt.tools/JNI Generation/org/eclipse/swt/tools/internal/NativesGenerator.java b/bundles/org.eclipse.swt.tools/JNI Generation/org/eclipse/swt/tools/internal/NativesGenerator.java
index 0a5fb323b77..b89572f3a5b 100644
--- a/bundles/org.eclipse.swt.tools/JNI Generation/org/eclipse/swt/tools/internal/NativesGenerator.java
+++ b/bundles/org.eclipse.swt.tools/JNI Generation/org/eclipse/swt/tools/internal/NativesGenerator.java
@@ -299,6 +299,14 @@ boolean generateGetParameter(JNIParameter param, boolean critical, int indent) {
output(iStr);
output(", NULL)");
}
+ } else if (componentType.isType("java.lang.String")) {
+ if (param.getFlag(FLAG_UNICODE)) {
+ throw new Error("not done");
+ }
+
+ output("swt_getArrayOfStringsUTF(env, arg");
+ output(iStr);
+ output(")");
} else {
throw new Error("not done");
}
@@ -381,6 +389,16 @@ void generateSetParameter(JNIParameter param, boolean critical) {
output("0");
}
output(");");
+ } else if (componentType.isType("java.lang.String")) {
+ if (param.getFlag(FLAG_UNICODE)) {
+ throw new Error("not done");
+ }
+
+ output("swt_releaseArrayOfStringsUTF(env, arg");
+ output(iStr);
+ output(", lparg");
+ output(iStr);
+ output(");");
} else {
throw new Error("not done");
}
@@ -452,6 +470,12 @@ boolean generateLocalVars(JNIParameter[] params, JNIType returnType) {
output(componentType.getTypeSignature2());
output(" *lparg" + i);
output("=NULL;");
+ } else if (componentType.isType("java.lang.String")) {
+ if (param.getFlag(FLAG_UNICODE)) {
+ output("jchar **lparg" + i + "=NULL");
+ } else {
+ output("char **lparg" + i+ "=NULL");
+ }
} else {
throw new Error("not done");
}
diff --git a/bundles/org.eclipse.swt.tools/JNI Generation/org/eclipse/swt/tools/internal/ReflectType.java b/bundles/org.eclipse.swt.tools/JNI Generation/org/eclipse/swt/tools/internal/ReflectType.java
index 81d90b458cd..50fd124094f 100644
--- a/bundles/org.eclipse.swt.tools/JNI Generation/org/eclipse/swt/tools/internal/ReflectType.java
+++ b/bundles/org.eclipse.swt.tools/JNI Generation/org/eclipse/swt/tools/internal/ReflectType.java
@@ -91,7 +91,10 @@ public String getTypeSignature2() {
if (clazz == String.class) return "jstring";
if (clazz == Class.class) return "jclass";
if (clazz.isArray()) {
- return getComponentType().getTypeSignature2() + "Array";
+ if (getComponentType().isPrimitive()) {
+ return getComponentType().getTypeSignature2() + "Array";
+ }
+ return "jobjectArray";
}
return "jobject";
}
diff --git a/bundles/org.eclipse.swt.tools/META-INF/MANIFEST.MF b/bundles/org.eclipse.swt.tools/META-INF/MANIFEST.MF
index 8e889fffa57..7798f42e14a 100644
--- a/bundles/org.eclipse.swt.tools/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.swt.tools/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-Name: %pluginName
Bundle-Vendor: %providerName
Bundle-SymbolicName: org.eclipse.swt.tools; singleton:=true
-Bundle-Version: 3.110.800.qualifier
+Bundle-Version: 3.110.900.qualifier
Bundle-ManifestVersion: 2
Export-Package: org.eclipse.swt.tools.internal; x-internal:=true
Bundle-ActivationPolicy: lazy
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/cocoa/org/eclipse/swt/dnd/Transfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/cocoa/org/eclipse/swt/dnd/Transfer.java
index 6950ec5b69f..fcc7bbf7028 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/cocoa/org/eclipse/swt/dnd/Transfer.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/cocoa/org/eclipse/swt/dnd/Transfer.java
@@ -136,7 +136,10 @@ public static int registerType(String formatName) {
int index = 1;
while (index < TYPES.length) {
String type = TYPES[index];
- if (type != null && formatName.equals(type)) {
+ if (type == null) {
+ break;
+ }
+ if (formatName.equals(type)) {
return index;
}
index++;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ByteArrayTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ByteArrayTransfer.java
index 7ea790bf899..b41c2a0b4da 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ByteArrayTransfer.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ByteArrayTransfer.java
@@ -13,6 +13,7 @@
*******************************************************************************/
package org.eclipse.swt.dnd;
+import org.eclipse.swt.dnd.TransferData.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.gtk.*;
@@ -136,6 +137,7 @@ public TransferData[] getSupportedTypes() {
@Override
public boolean isSupportedType(TransferData transferData){
+ if (GTK.GTK4) return isSupportedTypeGTK4(transferData);
if (transferData == null) return false;
int[] types = getTypeIds();
for (int i = 0; i < types.length; i++) {
@@ -144,6 +146,15 @@ public boolean isSupportedType(TransferData transferData){
return false;
}
+private boolean isSupportedTypeGTK4(TransferData transferData) {
+ if (transferData == null) return false;
+ int[] types = getTypeIds();
+ for (int i = 0; i < types.length; i++) {
+ if (transferData.gtk4().type == types[i]) return true;
+ }
+ return false;
+}
+
/**
* This implementation of javaToNative converts a java
* byte[] to a platform specific representation.
@@ -156,7 +167,11 @@ public boolean isSupportedType(TransferData transferData){
*/
@Override
protected void javaToNative (Object object, TransferData transferData) {
- transferData.result = 0;
+ if (GTK.GTK4) {
+ javaToNativeGTK4(object, transferData);
+ return;
+ }
+ transferData.gtk3().result = 0;
if (!checkByteArray(object) || !isSupportedType(transferData)) {
DND.error(DND.ERROR_INVALID_DATA);
}
@@ -165,10 +180,59 @@ protected void javaToNative (Object object, TransferData transferData) {
long pValue = OS.g_malloc(buffer.length);
if (pValue == 0) return;
C.memmove(pValue, buffer, buffer.length);
- transferData.length = buffer.length;
- transferData.format = 8;
- transferData.pValue = pValue;
- transferData.result = 1;
+ transferData.gtk3().length = buffer.length;
+ transferData.gtk3().format = 8;
+ transferData.gtk3().pValue = pValue;
+ transferData.gtk3().result = 1;
+}
+
+private void javaToNativeGTK4(Object object, TransferData transferData) {
+ if (!checkByteArray(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ byte[] buffer = (byte[]) object;
+ if (buffer.length == 0) {
+ return;
+ }
+ TransferDataGTK4 data = transferData.gtk4();
+ GdkContentSerializer serializer = data.serializer;
+
+ long pValue = OS.g_malloc(buffer.length);
+ if (pValue == 0) {
+ return;
+ }
+ C.memmove(pValue, buffer, buffer.length);
+
+// Sync version - this won't work if the other end of the stream is in our process (such as a Clipboard.getContents call).
+// long[] error = new long[1];
+// boolean finish = OS.g_output_stream_write_all(serializer.output_stream(), pValue, buffer.length, null,
+// serializer.cancellable(), error);
+// if (!finish) {
+// serializer.return_error(error[0]);
+// } else {
+// serializer.return_success();
+// }
+// Async version:
+ new AsyncFinishUtil().run(data.display, new AsyncReadyCallback() {
+ @Override
+ public void async(long result) {
+ OS.g_output_stream_write_all_async(serializer.output_stream(), pValue, buffer.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(pValue);
+ return 0;
+ }
+ });
}
/**
@@ -183,14 +247,56 @@ protected void javaToNative (Object object, TransferData transferData) {
*/
@Override
protected Object nativeToJava(TransferData transferData) {
- if ( !isSupportedType(transferData) || transferData.pValue == 0) return null;
- int size = transferData.format * transferData.length / 8;
+ if (GTK.GTK4) return nativeToJavaGTK4(transferData);
+ if ( !isSupportedType(transferData) || transferData.gtk3().pValue == 0) return null;
+ int size = transferData.gtk3().format * transferData.gtk3().length / 8;
if (size == 0) return null;
byte[] buffer = new byte[size];
- C.memmove(buffer, transferData.pValue, size);
+ C.memmove(buffer, transferData.gtk3().pValue, size);
return buffer;
}
+private Object nativeToJavaGTK4(TransferData transferData) {
+ TransferDataGTK4 data = transferData.gtk4();
+ if (!isSupportedType(transferData) || data.deserializer == null)
+ return null;
+
+ GdkContentDeserializer deserializer = data.deserializer;
+ long memoryStream = OS.g_memory_output_stream_new_resizable();
+ System.out.println("About to run g_output_stream_splice_async");
+ boolean success = new SyncFinishUtil().run(data.display, new SyncFinishCallback() {
+ @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 Boolean await(long result) {
+ long[] error = new long[1];
+ long spliced = OS.g_output_stream_splice_finish(memoryStream, result, null);
+ if (spliced < 0) {
+ deserializer.return_error(error[0]);
+ return false;
+ } else {
+ deserializer.return_success();
+ return true;
+ }
+ }
+ });
+
+ if (success) {
+ long data_size = OS.g_memory_output_stream_get_data_size(memoryStream);
+ long dataPtr = OS.g_memory_output_stream_get_data(memoryStream);
+ byte[] buffer = new byte[(int)data_size];
+ C.memmove(buffer, dataPtr, data_size);
+ return buffer;
+ }
+
+ return null;
+}
+
boolean checkByteArray(Object object) {
return (object instanceof byte[] && ((byte[])object).length > 0);
}
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..182a9de9299 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.*;
@@ -188,8 +187,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 +294,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");
@@ -312,9 +314,9 @@ public Object getContents(Transfer transfer, int clipboards) {
if (selection_data != 0) {
TransferData tdata = new TransferData();
tdata.type = GTK3.gtk_selection_data_get_data_type(selection_data);
- tdata.pValue = GTK3.gtk_selection_data_get_data(selection_data);
- tdata.length = GTK3.gtk_selection_data_get_length(selection_data);
- tdata.format = GTK3.gtk_selection_data_get_format(selection_data);
+ tdata.gtk3().pValue = GTK3.gtk_selection_data_get_data(selection_data);
+ tdata.gtk3().length = GTK3.gtk_selection_data_get_length(selection_data);
+ tdata.gtk3().format = GTK3.gtk_selection_data_get_format(selection_data);
result = transfer.nativeToJava(tdata);
GTK3.gtk_selection_data_free(selection_data);
selection_data = 0;
@@ -327,65 +329,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 +473,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);
+ }
}
}
@@ -625,6 +580,7 @@ public String[] getAvailableTypeNames() {
if(GTK.GTK4) {
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;
}
@@ -723,4 +679,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..f93fcb86516 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;
}
@@ -139,18 +135,15 @@ long getFunc(long clipboard, long selection_data, long info, long user_data_or_o
if (index == -1) return 0;
Object[] data = (clipboard == Clipboard.GTKCLIPBOARD) ? clipboardData : primaryClipboardData;
types[index].javaToNative(data[index], tdata);
- if (tdata.format < 8 || tdata.format % 8 != 0) {
+ if (tdata.gtk3().format < 8 || tdata.gtk3().format % 8 != 0) {
return 0;
}
- GTK3.gtk_selection_data_set(selection_data, tdata.type, tdata.format, tdata.pValue, tdata.length);
- OS.g_free(tdata.pValue);
+ GTK3.gtk_selection_data_set(selection_data, tdata.type, tdata.gtk3().format, tdata.gtk3().pValue, tdata.gtk3().length);
+ OS.g_free(tdata.gtk3().pValue);
return 1;
}
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..d9605e287ef
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ContentProviders.java
@@ -0,0 +1,313 @@
+/*******************************************************************************
+ * 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;
+ // make a transfer data and call
+ TransferData transferData = new TransferData();
+ transferData.gtk4().display = display;
+ transferData.gtk4().serializer = serializer;
+ transferData.gtk4().type = type;
+ transfer.javaToNative(object, transferData);
+ }
+
+ 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;
+ // make a transfer data and call
+ TransferData transferData = new TransferData();
+ transferData.gtk4().display = Display.getCurrent(); // TODO where to get display from? Is this OK?
+ transferData.gtk4().deserializer = deserializer;
+ transferData.gtk4().type = type;
+ Object object = transfer.nativeToJava(transferData);
+ // TODO save object better (see TODO where lastDeserializedObject is read)
+ this.lastDeserializedObject = object;
+ }
+
+ 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/DragSource.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/DragSource.java
index 07dfbd9addc..dfe937d98f3 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/DragSource.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/DragSource.java
@@ -516,9 +516,9 @@ void dragGetData(long widget, long context, long selection_data, int info, int
TransferData transferData = new TransferData();
transferData.type = target;
- transferData.pValue = data;
- transferData.length = length;
- transferData.format = format;
+ transferData.gtk3().pValue = data;
+ transferData.gtk3().length = length;
+ transferData.gtk3().format = format;
DNDEvent event = new DNDEvent();
event.widget = this;
@@ -536,9 +536,9 @@ void dragGetData(long widget, long context, long selection_data, int info, int
}
if (transfer == null) return;
transfer.javaToNative(event.data, transferData);
- if (transferData.result != 1) return;
- GTK3.gtk_selection_data_set(selection_data, transferData.type, transferData.format, transferData.pValue, transferData.length);
- OS.g_free(transferData.pValue);
+ if (transferData.gtk3().result != 1) return;
+ GTK3.gtk_selection_data_set(selection_data, transferData.type, transferData.gtk3().format, transferData.gtk3().pValue, transferData.gtk3().length);
+ OS.g_free(transferData.gtk3().pValue);
return;
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/DropTarget.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/DropTarget.java
index e82fbca3754..5f641b78e94 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/DropTarget.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/DropTarget.java
@@ -358,9 +358,9 @@ void drag_data_received ( long widget, long context, int x, int y, long selectio
long type = GTK3.gtk_selection_data_get_data_type(selection_data);
if (data != 0) {
transferData.type = type;
- transferData.length = length;
- transferData.pValue = data;
- transferData.format = format;
+ transferData.gtk3().length = length;
+ transferData.gtk3().pValue = data;
+ transferData.gtk3().format = format;
for (int i = 0; i < transferAgents.length; i++) {
Transfer transfer = transferAgents[i];
if (transfer != null && transfer.isSupportedType(transferData)) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/FileTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/FileTransfer.java
index a5682302ef9..670231d580f 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/FileTransfer.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/FileTransfer.java
@@ -69,7 +69,7 @@ public static FileTransfer getInstance () {
*/
@Override
public void javaToNative(Object object, TransferData transferData) {
- transferData.result = 0;
+ transferData.gtk3().result = 0;
if (!checkFile(object) || !isSupportedType(transferData)) {
DND.error(DND.ERROR_INVALID_DATA);
}
@@ -119,10 +119,10 @@ public void javaToNative(Object object, TransferData transferData) {
long ptr = OS.g_malloc(buffer.length+1);
C.memset(ptr, '\0', buffer.length+1);
C.memmove(ptr, buffer, buffer.length);
- transferData.pValue = ptr;
- transferData.length = buffer.length;
- transferData.format = 8;
- transferData.result = 1;
+ transferData.gtk3().pValue = ptr;
+ transferData.gtk3().length = buffer.length;
+ transferData.gtk3().format = 8;
+ transferData.gtk3().result = 1;
}
/**
* This implementation of nativeToJava converts a platform specific
@@ -137,10 +137,10 @@ public void javaToNative(Object object, TransferData transferData) {
*/
@Override
public Object nativeToJava(TransferData transferData) {
- if ( !isSupportedType(transferData) || transferData.pValue == 0 || transferData.length <= 0 ) return null;
- int length = transferData.length;
+ if ( !isSupportedType(transferData) || transferData.gtk3().pValue == 0 || transferData.gtk3().length <= 0 ) return null;
+ int length = transferData.gtk3().length;
byte[] temp = new byte[length];
- C.memmove(temp, transferData.pValue, length);
+ C.memmove(temp, transferData.gtk3().pValue, length);
boolean gnomeList = transferData.type == GNOME_LIST_ID;
int sepLength = gnomeList ? 1 : 2;
long [] files = new long [0];
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/HTMLTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/HTMLTransfer.java
index f9c8e36dfb7..cbd509db19b 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/HTMLTransfer.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/HTMLTransfer.java
@@ -61,7 +61,7 @@ public static HTMLTransfer getInstance () {
*/
@Override
public void javaToNative (Object object, TransferData transferData){
- transferData.result = 0;
+ transferData.gtk3().result = 0;
if (!checkHTML(object) || !isSupportedType(transferData)) {
DND.error(DND.ERROR_INVALID_DATA);
}
@@ -71,10 +71,10 @@ public void javaToNative (Object object, TransferData transferData){
long pValue = OS.g_malloc(byteCount);
if (pValue == 0) return;
C.memmove(pValue, utf8, byteCount);
- transferData.length = byteCount;
- transferData.format = 8;
- transferData.pValue = pValue;
- transferData.result = 1;
+ transferData.gtk3().length = byteCount;
+ transferData.gtk3().format = 8;
+ transferData.gtk3().pValue = pValue;
+ transferData.gtk3().result = 1;
}
/**
@@ -89,21 +89,21 @@ public void javaToNative (Object object, TransferData transferData){
*/
@Override
public Object nativeToJava(TransferData transferData){
- if ( !isSupportedType(transferData) || transferData.pValue == 0 ) return null;
+ if ( !isSupportedType(transferData) || transferData.gtk3().pValue == 0 ) return null;
/* Ensure byteCount is a multiple of 2 bytes */
- int size = (transferData.format * transferData.length / 8) / 2 * 2;
+ int size = (transferData.gtk3().format * transferData.gtk3().length / 8) / 2 * 2;
if (size <= 0) return null;
char[] bom = new char[1]; // look for a Byte Order Mark
- if (size > 1) C.memmove (bom, transferData.pValue, 2);
+ if (size > 1) C.memmove (bom, transferData.gtk3().pValue, 2);
String string;
if (bom[0] == '\ufeff' || bom[0] == '\ufffe') {
// utf16
char[] chars = new char [size/2];
- C.memmove (chars, transferData.pValue, size);
+ C.memmove (chars, transferData.gtk3().pValue, size);
string = new String (chars);
} else {
byte[] utf8 = new byte[size];
- C.memmove(utf8, transferData.pValue, size);
+ C.memmove(utf8, transferData.gtk3().pValue, size);
// convert utf8 byte array to a unicode string
char [] unicode = org.eclipse.swt.internal.Converter.mbcsToWcs (utf8);
string = new String (unicode);
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..055e60cfa8a 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() {}
@@ -111,14 +111,14 @@ public void javaToNative(Object object, TransferData transferData) {
if (type == null) return;
GDK.gdk_pixbuf_save_to_bufferv(pixbuf, buffer, len, type, null, null, null);
OS.g_object_unref(pixbuf);
- transferData.pValue = buffer[0];
- transferData.length = (int)(len[0] + 3) / 4 * 4;
- transferData.result = 1;
+ transferData.gtk3().pValue = buffer[0];
+ transferData.gtk3().length = (int)(len[0] + 3) / 4 * 4;
+ transferData.gtk3().result = 1;
// The following value has been changed from 32 to 8 as a simple fix for #146
// See https://www.cc.gatech.edu/data_files/public/doc/gtk/tutorial/gtk_tut-16.html where it states:
// "The format field is actually important here - the X server uses it to figure out whether the data
// needs to be byte-swapped or not. Usually it will be 8 - i.e. a character - or 32 - i.e. a. integer."
- transferData.format = 8;
+ transferData.gtk3().format = 8;
}
image.dispose();
}
@@ -136,10 +136,10 @@ public void javaToNative(Object object, TransferData transferData) {
@Override
public Object nativeToJava(TransferData transferData) {
ImageData imgData = null;
- if (transferData.length > 0) {
+ if (transferData.gtk3().length > 0) {
long loader = GDK.gdk_pixbuf_loader_new();
try {
- GDK.gdk_pixbuf_loader_write(loader, transferData.pValue, transferData.length, null);
+ GDK.gdk_pixbuf_loader_write(loader, transferData.gtk3().pValue, transferData.gtk3().length, null);
GDK.gdk_pixbuf_loader_close(loader, null);
long pixbuf = GDK.gdk_pixbuf_loader_get_pixbuf(loader);
if (pixbuf != 0) {
@@ -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..71b9473376c 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
@@ -13,6 +13,7 @@
*******************************************************************************/
package org.eclipse.swt.dnd;
+import org.eclipse.swt.dnd.TransferData.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.gtk.*;
@@ -63,7 +64,11 @@ public static RTFTransfer getInstance () {
*/
@Override
public void javaToNative (Object object, TransferData transferData){
- transferData.result = 0;
+ if (GTK.GTK4) {
+ javaToNativeGTK4(object, transferData);
+ return;
+ }
+ transferData.gtk3().result = 0;
if (!checkRTF(object) || !isSupportedType(transferData)) {
DND.error(DND.ERROR_INVALID_DATA);
}
@@ -72,10 +77,18 @@ public void javaToNative (Object object, TransferData transferData){
long pValue = OS.g_malloc(buffer.length);
if (pValue == 0) return;
C.memmove(pValue, buffer, buffer.length);
- transferData.length = buffer.length - 1;
- transferData.format = 8;
- transferData.pValue = pValue;
- transferData.result = 1;
+ transferData.gtk3().length = buffer.length - 1;
+ transferData.gtk3().format = 8;
+ transferData.gtk3().pValue = pValue;
+ transferData.gtk3().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);
}
/**
@@ -90,17 +103,29 @@ public void javaToNative (Object object, TransferData transferData){
*/
@Override
public Object nativeToJava(TransferData transferData){
- if ( !isSupportedType(transferData) || transferData.pValue == 0 ) return null;
- int size = transferData.format * transferData.length / 8;
+ if (GTK.GTK4) return nativeToJavaGTK4(transferData);
+
+ if ( !isSupportedType(transferData) || transferData.gtk3().pValue == 0 ) return null;
+ int size = transferData.gtk3().format * transferData.gtk3().length / 8;
if (size == 0) return null;
byte[] buffer = new byte[size];
- C.memmove(buffer, transferData.pValue, size);
+ C.memmove(buffer, transferData.gtk3().pValue, size);
char [] chars = Converter.mbcsToWcs (buffer);
String string = new String (chars);
int end = string.indexOf('\0');
return (end == -1) ? string : string.substring(0, end);
}
+private Object nativeToJavaGTK4(TransferData transferData) {
+ TransferDataGTK4 data = transferData.gtk4();
+ if (!isSupportedType(transferData) || data.deserializer == null) return null;
+ 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..b32be5aee27 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
@@ -13,6 +13,7 @@
*******************************************************************************/
package org.eclipse.swt.dnd;
+import org.eclipse.swt.dnd.TransferData.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.gtk.*;
@@ -42,11 +43,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,7 +74,11 @@ public static TextTransfer getInstance () {
*/
@Override
public void javaToNative (Object object, TransferData transferData) {
- transferData.result = 0;
+ if (GTK.GTK4) {
+ javaToNativeGTK4(object, transferData);
+ return;
+ }
+ transferData.gtk3().result = 0;
if (!checkText(object) || !isSupportedType(transferData)) {
DND.error(DND.ERROR_INVALID_DATA);
}
@@ -85,32 +92,39 @@ public void javaToNative (Object object, TransferData transferData) {
boolean result = GDK.gdk_x11_display_utf8_to_compound_text (GDK.gdk_display_get_default(), utf8, encoding, format, ctext, length);
if (!result) return;
transferData.type = encoding[0];
- transferData.format = format[0];
- transferData.length = length[0];
- transferData.pValue = ctext[0];
- transferData.result = 1;
+ transferData.gtk3().format = format[0];
+ transferData.gtk3().length = length[0];
+ transferData.gtk3().pValue = ctext[0];
+ transferData.gtk3().result = 1;
}
if (transferData.type == UTF8_STRING_ID || transferData.type == TEXT_PLAIN_UTF8_ID) {
long pValue = OS.g_malloc(utf8.length);
if (pValue == 0) return;
C.memmove(pValue, utf8, utf8.length);
- transferData.format = 8;
- transferData.length = utf8.length - 1;
- transferData.pValue = pValue;
- transferData.result = 1;
+ transferData.gtk3().format = 8;
+ transferData.gtk3().length = utf8.length - 1;
+ transferData.gtk3().pValue = pValue;
+ transferData.gtk3().result = 1;
}
if (transferData.type == STRING_ID) {
long string_target = GDK.gdk_utf8_to_string_target(utf8);
if (string_target == 0) return;
transferData.type = STRING_ID;
- transferData.format = 8;
- transferData.length = C.strlen(string_target);
- transferData.pValue = string_target;
- transferData.result = 1;
+ transferData.gtk3().format = 8;
+ transferData.gtk3().length = C.strlen(string_target);
+ transferData.gtk3().pValue = string_target;
+ transferData.gtk3().result = 1;
}
}
+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,9 +136,11 @@ public void javaToNative (Object object, TransferData transferData) {
*/
@Override
public Object nativeToJava(TransferData transferData){
- if (!isSupportedType(transferData) || transferData.pValue == 0) return null;
+ if (GTK.GTK4) return nativeToJavaGTK4(transferData);
+
+ if (!isSupportedType(transferData) || transferData.gtk3().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);
+ int count = GDK.gdk_text_property_to_utf8_list_for_display(GDK.gdk_display_get_default(), transferData.type, transferData.gtk3().format, transferData.gtk3().pValue, transferData.gtk3().length, list);
if (count == 0) return null;
long [] ptr = new long [1];
C.memmove(ptr, list[0], C.PTR_SIZEOF);
@@ -139,10 +155,20 @@ public Object nativeToJava(TransferData transferData){
return (end == -1) ? string : string.substring(0, end);
}
+private Object nativeToJavaGTK4(TransferData transferData) {
+ TransferDataGTK4 data = transferData.gtk4();
+ if (!isSupportedType(transferData) || data.deserializer == null) return null;
+ 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 +179,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..658ae5b790e 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 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
@@ -13,6 +13,10 @@
*******************************************************************************/
package org.eclipse.swt.dnd;
+import java.util.function.*;
+
+import org.eclipse.swt.internal.gtk.*;
+import org.eclipse.swt.widgets.*;
/**
* The TransferData class is a platform specific data structure for
@@ -46,66 +50,119 @@ public class TransferData {
public long type;
/**
- * Specifies the number of units in pValue.
- * (Warning: This field is platform dependent)
- *
- * IMPORTANT: This field is not part of the SWT
- * public API. It is marked public only so that it can be shared
- * within the packages provided by SWT. It is not available on all
- * platforms and should never be accessed from application code.
- *
- *
- * @see TransferData#format for the size of one unit
- *
- * @noreference This field is not intended to be referenced by clients.
+ * @noreference This class is not intended to be referenced by clients.
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ * @noextend This class is not intended to be subclassed by clients.
+ * @since 3.132
*/
- public int length;
+ public static class TransferDataGTK3 {
+ /**
+ * Specifies the number of units in pValue.
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ *
+ * @see TransferDataGTK3#format for the size of one unit
+ *
+ * @noreference This field is not intended to be referenced by clients.
+ */
+ public int length;
+ /**
+ * Specifies the size in bits of a single unit in pValue.
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ *
+ * This is most commonly 8 bits.
+ *
+ * @noreference This field is not intended to be referenced by clients.
+ */
+ public int format;
+ /**
+ * Pointer to the data being transferred.
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ *
+ * @noreference This field is not intended to be referenced by clients.
+ */
+ public long pValue;
+ /**
+ * The result field contains the result of converting a
+ * java data type into a platform specific value.
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ *
The value of result is 1 if the conversion was successful.
+ * The value of result is 0 if the conversion failed.
+ *
+ * @noreference This field is not intended to be referenced by clients.
+ */
+ public int result;
+
+ private TransferDataGTK3() {}
+ }
/**
- * Specifies the size in bits of a single unit in pValue.
- * (Warning: This field is platform dependent)
- *
- * IMPORTANT: This field is not part of the SWT
- * public API. It is marked public only so that it can be shared
- * within the packages provided by SWT. It is not available on all
- * platforms and should never be accessed from application code.
- *
- *
- * This is most commonly 8 bits.
- *
- * @noreference This field is not intended to be referenced by clients.
+ * @noreference This class is not intended to be referenced by clients.
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ * @noextend This class is not intended to be subclassed by clients.
+ * @since 3.132
*/
- public int format;
+ public static class TransferDataGTK4 {
+ public GdkContentSerializer serializer;
+ public Display display;
+ public int type;
+ public GdkContentDeserializer deserializer;
+ public Consumer