Skip to content

Commit 0bbfb8c

Browse files
committed
WIP - [GTK4] support Clipboard
Fixes #2126
1 parent 43f54cc commit 0bbfb8c

File tree

41 files changed

+2965
-335
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2965
-335
lines changed

bundles/org.eclipse.swt.tools/JNI Generation/org/eclipse/swt/tools/internal/ASTType.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,10 @@ public String getTypeSignature2() {
148148
if (name.equals("Ljava/lang/String;")) return "jstring";
149149
if (name.equals("Ljava/lang/Class;")) return "jclass";
150150
if (isArray()) {
151-
return getComponentType().getTypeSignature2() + "Array";
151+
if (getComponentType().isPrimitive()) {
152+
return getComponentType().getTypeSignature2() + "Array";
153+
}
154+
return "jobjectArray";
152155
}
153156
return "jobject";
154157
}

bundles/org.eclipse.swt.tools/JNI Generation/org/eclipse/swt/tools/internal/NativesGenerator.java

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,57 @@ public void generate(JNIClass clazz) {
7777
sort(methods);
7878
generateNativeMacro(clazz);
7979
generateWarningSettings();
80+
generateStaticMethods();
8081
generateExcludes(methods);
8182
generate(methods);
8283
}
84+
private void generateStaticMethods() {
85+
if (!getOutputName().equals("gtk4")) {
86+
return;
87+
}
88+
89+
outputln("""
90+
static char **
91+
getArrayOfStringsUTF(JNIEnv *env, jobjectArray javaArray) {
92+
jsize length = (*env)->GetArrayLength(env, javaArray);
93+
94+
char **cStrings = (char **)malloc((length + 1) * sizeof(char*));
95+
if (!cStrings) {
96+
return NULL;
97+
}
98+
99+
for (jsize i = 0; i < length; i++) {
100+
jstring jstr = (jstring)(*env)->GetObjectArrayElement(env, javaArray, i);
101+
if (jstr) {
102+
const char *utfStr = (*env)->GetStringUTFChars(env, jstr, 0);
103+
104+
cStrings[i] = strdup(utfStr);
105+
106+
(*env)->ReleaseStringUTFChars(env, jstr, utfStr);
107+
(*env)->DeleteLocalRef(env, jstr);
108+
} else {
109+
cStrings[i] = NULL;
110+
}
111+
}
112+
113+
cStrings[length] = NULL;
114+
return cStrings;
115+
}
116+
117+
static void
118+
releaseArrayOfStringsUTF(JNIEnv *env, jobjectArray javaArray, char **cStrings) {
119+
jsize length = (*env)->GetArrayLength(env, javaArray);
120+
121+
for (jsize i = 0; i < length; i++) {
122+
if (cStrings[i]) {
123+
free(cStrings[i]);
124+
}
125+
}
126+
free(cStrings);
127+
}
128+
129+
""");
130+
}
83131

84132
public void generate(JNIMethod[] methods) {
85133
sort(methods);
@@ -299,6 +347,14 @@ boolean generateGetParameter(JNIParameter param, boolean critical, int indent) {
299347
output(iStr);
300348
output(", NULL)");
301349
}
350+
} else if (componentType.isType("java.lang.String")) {
351+
if (param.getFlag(FLAG_UNICODE)) {
352+
throw new Error("not done");
353+
}
354+
355+
output("getArrayOfStringsUTF(env, arg");
356+
output(iStr);
357+
output(")");
302358
} else {
303359
throw new Error("not done");
304360
}
@@ -381,6 +437,16 @@ void generateSetParameter(JNIParameter param, boolean critical) {
381437
output("0");
382438
}
383439
output(");");
440+
} else if (componentType.isType("java.lang.String")) {
441+
if (param.getFlag(FLAG_UNICODE)) {
442+
throw new Error("not done");
443+
}
444+
445+
output("releaseArrayOfStringsUTF(env, arg");
446+
output(iStr);
447+
output(", lparg");
448+
output(iStr);
449+
output(");");
384450
} else {
385451
throw new Error("not done");
386452
}
@@ -452,6 +518,12 @@ boolean generateLocalVars(JNIParameter[] params, JNIType returnType) {
452518
output(componentType.getTypeSignature2());
453519
output(" *lparg" + i);
454520
output("=NULL;");
521+
} else if (componentType.isType("java.lang.String")) {
522+
if (param.getFlag(FLAG_UNICODE)) {
523+
output("jchar **lparg" + i + "=NULL");
524+
} else {
525+
output("char **lparg" + i+ "=NULL");
526+
}
455527
} else {
456528
throw new Error("not done");
457529
}

bundles/org.eclipse.swt.tools/JNI Generation/org/eclipse/swt/tools/internal/ReflectType.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,10 @@ public String getTypeSignature2() {
9191
if (clazz == String.class) return "jstring";
9292
if (clazz == Class.class) return "jclass";
9393
if (clazz.isArray()) {
94-
return getComponentType().getTypeSignature2() + "Array";
94+
if (getComponentType().isPrimitive()) {
95+
return getComponentType().getTypeSignature2() + "Array";
96+
}
97+
return "jobjectArray";
9598
}
9699
return "jobject";
97100
}

bundles/org.eclipse.swt.tools/META-INF/MANIFEST.MF

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ Manifest-Version: 1.0
22
Bundle-Name: %pluginName
33
Bundle-Vendor: %providerName
44
Bundle-SymbolicName: org.eclipse.swt.tools; singleton:=true
5-
Bundle-Version: 3.110.800.qualifier
5+
Bundle-Version: 3.110.900.qualifier
66
Bundle-ManifestVersion: 2
77
Export-Package: org.eclipse.swt.tools.internal; x-internal:=true
88
Bundle-ActivationPolicy: lazy
99
Bundle-Localization: plugin
10-
Bundle-RequiredExecutionEnvironment: JavaSE-17
10+
Bundle-RequiredExecutionEnvironment: JavaSE-21
1111
Require-Bundle: org.eclipse.core.runtime;bundle-version="3.29.0",
1212
org.eclipse.core.resources;bundle-version="3.4.0",
1313
org.eclipse.jdt.core;bundle-version="3.4.0",

bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/cocoa/org/eclipse/swt/dnd/Transfer.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,10 @@ public static int registerType(String formatName) {
136136
int index = 1;
137137
while (index < TYPES.length) {
138138
String type = TYPES[index];
139-
if (type != null && formatName.equals(type)) {
139+
if (type == null) {
140+
break;
141+
}
142+
if (formatName.equals(type)) {
140143
return index;
141144
}
142145
index++;

bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ByteArrayTransfer.java

Lines changed: 114 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
*******************************************************************************/
1414
package org.eclipse.swt.dnd;
1515

16+
import org.eclipse.swt.dnd.TransferData.*;
1617
import org.eclipse.swt.internal.*;
1718
import org.eclipse.swt.internal.gtk.*;
1819

@@ -136,6 +137,7 @@ public TransferData[] getSupportedTypes() {
136137

137138
@Override
138139
public boolean isSupportedType(TransferData transferData){
140+
if (GTK.GTK4) return isSupportedTypeGTK4(transferData);
139141
if (transferData == null) return false;
140142
int[] types = getTypeIds();
141143
for (int i = 0; i < types.length; i++) {
@@ -144,6 +146,15 @@ public boolean isSupportedType(TransferData transferData){
144146
return false;
145147
}
146148

149+
private boolean isSupportedTypeGTK4(TransferData transferData) {
150+
if (transferData == null) return false;
151+
int[] types = getTypeIds();
152+
for (int i = 0; i < types.length; i++) {
153+
if (transferData.gtk4().type == types[i]) return true;
154+
}
155+
return false;
156+
}
157+
147158
/**
148159
* This implementation of <code>javaToNative</code> converts a java
149160
* <code>byte[]</code> to a platform specific representation.
@@ -156,7 +167,11 @@ public boolean isSupportedType(TransferData transferData){
156167
*/
157168
@Override
158169
protected void javaToNative (Object object, TransferData transferData) {
159-
transferData.result = 0;
170+
if (GTK.GTK4) {
171+
javaToNativeGTK4(object, transferData);
172+
return;
173+
}
174+
transferData.gtk3().result = 0;
160175
if (!checkByteArray(object) || !isSupportedType(transferData)) {
161176
DND.error(DND.ERROR_INVALID_DATA);
162177
}
@@ -165,10 +180,59 @@ protected void javaToNative (Object object, TransferData transferData) {
165180
long pValue = OS.g_malloc(buffer.length);
166181
if (pValue == 0) return;
167182
C.memmove(pValue, buffer, buffer.length);
168-
transferData.length = buffer.length;
169-
transferData.format = 8;
170-
transferData.pValue = pValue;
171-
transferData.result = 1;
183+
transferData.gtk3().length = buffer.length;
184+
transferData.gtk3().format = 8;
185+
transferData.gtk3().pValue = pValue;
186+
transferData.gtk3().result = 1;
187+
}
188+
189+
private void javaToNativeGTK4(Object object, TransferData transferData) {
190+
if (!checkByteArray(object) || !isSupportedType(transferData)) {
191+
DND.error(DND.ERROR_INVALID_DATA);
192+
}
193+
byte[] buffer = (byte[]) object;
194+
if (buffer.length == 0) {
195+
return;
196+
}
197+
TransferDataGTK4 data = transferData.gtk4();
198+
GdkContentSerializer serializer = data.serializer;
199+
200+
long pValue = OS.g_malloc(buffer.length);
201+
if (pValue == 0) {
202+
return;
203+
}
204+
C.memmove(pValue, buffer, buffer.length);
205+
206+
// Sync version - this won't work if the other end of the stream is in our process (such as a Clipboard.getContents call).
207+
// long[] error = new long[1];
208+
// boolean finish = OS.g_output_stream_write_all(serializer.output_stream(), pValue, buffer.length, null,
209+
// serializer.cancellable(), error);
210+
// if (!finish) {
211+
// serializer.return_error(error[0]);
212+
// } else {
213+
// serializer.return_success();
214+
// }
215+
// Async version:
216+
new AsyncFinishUtil().run(data.display, new AsyncReadyCallback() {
217+
@Override
218+
public void async(long result) {
219+
OS.g_output_stream_write_all_async(serializer.output_stream(), pValue, buffer.length, serializer.priority(),
220+
serializer.cancellable(), result, 0);
221+
}
222+
223+
@Override
224+
public long await(long result) {
225+
long[] error = new long[1];
226+
boolean finish = OS.g_output_stream_write_all_finish(serializer.output_stream(), result, null, error);
227+
if (!finish) {
228+
serializer.return_error(error[0]);
229+
} else {
230+
serializer.return_success();
231+
}
232+
OS.g_free(pValue);
233+
return 0;
234+
}
235+
});
172236
}
173237

174238
/**
@@ -183,14 +247,56 @@ protected void javaToNative (Object object, TransferData transferData) {
183247
*/
184248
@Override
185249
protected Object nativeToJava(TransferData transferData) {
186-
if ( !isSupportedType(transferData) || transferData.pValue == 0) return null;
187-
int size = transferData.format * transferData.length / 8;
250+
if (GTK.GTK4) return nativeToJavaGTK4(transferData);
251+
if ( !isSupportedType(transferData) || transferData.gtk3().pValue == 0) return null;
252+
int size = transferData.gtk3().format * transferData.gtk3().length / 8;
188253
if (size == 0) return null;
189254
byte[] buffer = new byte[size];
190-
C.memmove(buffer, transferData.pValue, size);
255+
C.memmove(buffer, transferData.gtk3().pValue, size);
191256
return buffer;
192257
}
193258

259+
private Object nativeToJavaGTK4(TransferData transferData) {
260+
TransferDataGTK4 data = transferData.gtk4();
261+
if (!isSupportedType(transferData) || data.deserializer == null)
262+
return null;
263+
264+
GdkContentDeserializer deserializer = data.deserializer;
265+
long memoryStream = OS.g_memory_output_stream_new_resizable();
266+
System.out.println("About to run g_output_stream_splice_async");
267+
boolean success = new SyncFinishUtil<Boolean>().run(data.display, new SyncFinishCallback<Boolean>() {
268+
@Override
269+
public void async(long result) {
270+
OS.g_output_stream_splice_async(memoryStream, deserializer.input_stream(),
271+
OS.G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | OS.G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
272+
deserializer.priority(), deserializer.cancellable(), result, 0);
273+
}
274+
275+
@Override
276+
public Boolean await(long result) {
277+
long[] error = new long[1];
278+
long spliced = OS.g_output_stream_splice_finish(memoryStream, result, null);
279+
if (spliced < 0) {
280+
deserializer.return_error(error[0]);
281+
return false;
282+
} else {
283+
deserializer.return_success();
284+
return true;
285+
}
286+
}
287+
});
288+
289+
if (success) {
290+
long data_size = OS.g_memory_output_stream_get_data_size(memoryStream);
291+
long dataPtr = OS.g_memory_output_stream_get_data(memoryStream);
292+
byte[] buffer = new byte[(int)data_size];
293+
C.memmove(buffer, dataPtr, data_size);
294+
return buffer;
295+
}
296+
297+
return null;
298+
}
299+
194300
boolean checkByteArray(Object object) {
195301
return (object instanceof byte[] && ((byte[])object).length > 0);
196302
}

0 commit comments

Comments
 (0)