From 82ca8d527a2b32acd843eef5ebdd2305f065dbd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=8A?= =?UTF-8?q?=D1=80=20=D0=9A=D1=83=D1=80=D1=82=D0=B0=D0=BA=D0=BE=D0=B2?= Date: Thu, 2 Jul 2026 10:05:54 +0300 Subject: [PATCH] [GTK4] Implement DropTarget async drop handling Implement GTK4 DropTarget support using GtkDropTargetAsync with accept, enter/motion/leave and drop handlers. Add GTK4 drop data flow integration by matching offered GTypes, reading drop values asynchronously via gdk_drop_read_value_async/finish, and finishing drops with the selected action. Tested with DNDExample. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../gtk/org/eclipse/swt/dnd/DropTarget.java | 464 +++++++++++++++--- .../Eclipse SWT PI/gtk/library/gtk4.c | 82 ++++ .../Eclipse SWT PI/gtk/library/gtk4_stats.h | 7 + .../gtk/org/eclipse/swt/internal/gtk/OS.java | 3 + .../org/eclipse/swt/internal/gtk4/GTK4.java | 35 ++ 5 files changed, 512 insertions(+), 79 deletions(-) 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 6ca2c9a334a..c01333c0ee7 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 @@ -14,9 +14,12 @@ package org.eclipse.swt.dnd; +import java.lang.reflect.*; + import org.eclipse.swt.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.internal.*; +import org.eclipse.swt.internal.GAsyncReadyCallbackHelper.*; import org.eclipse.swt.internal.gtk.*; import org.eclipse.swt.internal.gtk3.*; import org.eclipse.swt.internal.gtk4.*; @@ -111,11 +114,26 @@ public class DropTarget extends Widget { static Callback Drag_Data_Received; static Callback Drag_Drop; + /* GTK4 specific callbacks for GtkDropTargetAsync signals */ + static Callback DropAccept; + static Callback DropEnter; + static Callback DropMotion; + static Callback DropLeave; + static Callback Drop; + static { - Drag_Motion = new Callback(DropTarget.class, "Drag_Motion", 5); //$NON-NLS-1$ - Drag_Leave = new Callback(DropTarget.class, "Drag_Leave", 3); //$NON-NLS-1$ - Drag_Data_Received = new Callback(DropTarget.class, "Drag_Data_Received", 7); //$NON-NLS-1$ - Drag_Drop = new Callback(DropTarget.class, "Drag_Drop", 5); //$NON-NLS-1$ + if (GTK.GTK4) { + DropAccept = new Callback(DropTarget.class, "DropAccept", long.class, new Type[] {long.class, long.class}); //$NON-NLS-1$ + DropEnter = new Callback(DropTarget.class, "DropEnter", long.class, new Type[] {long.class, long.class, double.class, double.class}); //$NON-NLS-1$ + DropMotion = new Callback(DropTarget.class, "DropMotion", long.class, new Type[] {long.class, long.class, double.class, double.class}); //$NON-NLS-1$ + DropLeave = new Callback(DropTarget.class, "DropLeave", void.class, new Type[] {long.class, long.class}); //$NON-NLS-1$ + Drop = new Callback(DropTarget.class, "Drop", long.class, new Type[] {long.class, long.class, double.class, double.class}); //$NON-NLS-1$ + } else { + Drag_Motion = new Callback(DropTarget.class, "Drag_Motion", 5); //$NON-NLS-1$ + Drag_Leave = new Callback(DropTarget.class, "Drag_Leave", 3); //$NON-NLS-1$ + Drag_Data_Received = new Callback(DropTarget.class, "Drag_Data_Received", 7); //$NON-NLS-1$ + Drag_Drop = new Callback(DropTarget.class, "Drag_Drop", 5); //$NON-NLS-1$ + } } /* GTK4 specific */ @@ -157,10 +175,23 @@ public DropTarget(Control control, int style) { this.control = control; if (GTK.GTK4) { + if (DropAccept == null || DropEnter == null || DropMotion == null || DropLeave == null || Drop == null) { + DND.error(DND.ERROR_CANNOT_INIT_DROP); + } + if (control.getData(DND.DROP_TARGET_KEY) != null) { + DND.error(DND.ERROR_CANNOT_INIT_DROP); + } + control.setData(DND.DROP_TARGET_KEY, this); + int actions = opToOsOp(style); dropController = GTK4.gtk_drop_target_async_new(0, actions); - GTK4.gtk_widget_add_controller(control.handle, dropController); + + OS.g_signal_connect(dropController, OS.accept, DropAccept.getAddress(), 0); + OS.g_signal_connect(dropController, OS.drag_enter, DropEnter.getAddress(), 0); + OS.g_signal_connect(dropController, OS.drag_motion, DropMotion.getAddress(), 0); + OS.g_signal_connect(dropController, OS.drag_leave, DropLeave.getAddress(), 0); + OS.g_signal_connect(dropController, OS.drop, Drop.getAddress(), 0); } else { if (Drag_Motion == null || Drag_Leave == null || Drag_Data_Received == null || Drag_Drop == null) { DND.error(DND.ERROR_CANNOT_INIT_DROP); @@ -176,74 +207,74 @@ public DropTarget(Control control, int style) { drag_leave_handler = OS.g_signal_connect(control.handle, OS.drag_leave, Drag_Leave.getAddress(), 0); drag_data_received_handler = OS.g_signal_connect(control.handle, OS.drag_data_received, Drag_Data_Received.getAddress(), 0); drag_drop_handler = OS.g_signal_connect(control.handle, OS.drag_drop, Drag_Drop.getAddress(), 0); + } - // Dispose listeners - controlListener = event -> { - if (!DropTarget.this.isDisposed()){ - DropTarget.this.dispose(); - } - }; - control.addListener(SWT.Dispose, controlListener); - - this.addListener(SWT.Dispose, event -> onDispose()); - - Object effect = control.getData(DEFAULT_DROP_TARGET_EFFECT); - if (effect instanceof DropTargetEffect) { - dropEffect = (DropTargetEffect) effect; - } else if (control instanceof Table) { - dropEffect = new TableDropTargetEffect((Table) control); - } else if (control instanceof Tree) { - dropEffect = new TreeDropTargetEffect((Tree) control); + // Dispose listeners + controlListener = event -> { + if (!DropTarget.this.isDisposed()){ + DropTarget.this.dispose(); } + }; + control.addListener(SWT.Dispose, controlListener); + + this.addListener(SWT.Dispose, event -> onDispose()); + + Object effect = control.getData(DEFAULT_DROP_TARGET_EFFECT); + if (effect instanceof DropTargetEffect) { + dropEffect = (DropTargetEffect) effect; + } else if (control instanceof Table) { + dropEffect = new TableDropTargetEffect((Table) control); + } else if (control instanceof Tree) { + dropEffect = new TreeDropTargetEffect((Tree) control); + } - dragOverHeartbeat = () -> { - Control control1 = DropTarget.this.control; - if (control1 == null || control1.isDisposed() || dragOverStart == 0) return; - long time = System.currentTimeMillis(); - int delay = DRAGOVER_HYSTERESIS; - if (time < dragOverStart) { - delay = (int)(dragOverStart - time); - } else { - dragOverEvent.time += DRAGOVER_HYSTERESIS; - int allowedOperations = dragOverEvent.operations; - TransferData[] allowedTypes = dragOverEvent.dataTypes; - //pass a copy of data types in to listeners in case application modifies it - TransferData[] dataTypes = new TransferData[allowedTypes.length]; - System.arraycopy(allowedTypes, 0, dataTypes, 0, dataTypes.length); - - DNDEvent event = new DNDEvent(); - event.widget = dragOverEvent.widget; - event.x = dragOverEvent.x; - event.y = dragOverEvent.y; - event.time = dragOverEvent.time; - event.feedback = DND.FEEDBACK_SELECT; - event.dataTypes = dataTypes; - event.dataType = selectedDataType; - event.operations = dragOverEvent.operations; - event.detail = selectedOperation; - if (dropEffect != null) { - event.item = dropEffect.getItem(dragOverEvent.x, dragOverEvent.y); - } - selectedDataType = null; - selectedOperation = DND.DROP_NONE; - notifyListeners(DND.DragOver, event); - if (event.dataType != null) { - for (int i = 0; i < allowedTypes.length; i++) { - if (allowedTypes[i].type == event.dataType.type) { - selectedDataType = event.dataType; - break; - } + dragOverHeartbeat = () -> { + Control control1 = DropTarget.this.control; + if (control1 == null || control1.isDisposed() || dragOverStart == 0) return; + long time = System.currentTimeMillis(); + int delay = DRAGOVER_HYSTERESIS; + if (time < dragOverStart) { + delay = (int)(dragOverStart - time); + } else { + dragOverEvent.time += DRAGOVER_HYSTERESIS; + int allowedOperations = dragOverEvent.operations; + TransferData[] allowedTypes = dragOverEvent.dataTypes; + //pass a copy of data types in to listeners in case application modifies it + TransferData[] dataTypes = new TransferData[allowedTypes.length]; + System.arraycopy(allowedTypes, 0, dataTypes, 0, dataTypes.length); + + DNDEvent event = new DNDEvent(); + event.widget = dragOverEvent.widget; + event.x = dragOverEvent.x; + event.y = dragOverEvent.y; + event.time = dragOverEvent.time; + event.feedback = DND.FEEDBACK_SELECT; + event.dataTypes = dataTypes; + event.dataType = selectedDataType; + event.operations = dragOverEvent.operations; + event.detail = selectedOperation; + if (dropEffect != null) { + event.item = dropEffect.getItem(dragOverEvent.x, dragOverEvent.y); + } + selectedDataType = null; + selectedOperation = DND.DROP_NONE; + notifyListeners(DND.DragOver, event); + if (event.dataType != null) { + for (int i = 0; i < allowedTypes.length; i++) { + if (allowedTypes[i].type == event.dataType.type) { + selectedDataType = event.dataType; + break; } } - if (selectedDataType != null && (event.detail & allowedOperations) != 0) { - selectedOperation = event.detail; - } } - control1 = DropTarget.this.control; - if (control1 == null || control1.isDisposed()) return; - control1.getDisplay().timerExec(delay, dragOverHeartbeat); - }; - } + if (selectedDataType != null && (event.detail & allowedOperations) != 0) { + selectedOperation = event.detail; + } + } + control1 = DropTarget.this.control; + if (control1 == null || control1.isDisposed()) return; + control1.getDisplay().timerExec(delay, dragOverHeartbeat); + }; } static int checkStyle (int style) { @@ -285,6 +316,42 @@ static DropTarget FindDropTarget(long handle) { return (DropTarget)widget.getData(DND.DROP_TARGET_KEY); } +static DropTarget FindDropTargetGtk4(long controller) { + long widget = GTK.gtk_event_controller_get_widget(controller); + if (widget == 0) return null; + return FindDropTarget(widget); +} + +static long DropAccept(long controller, long drop) { + DropTarget target = FindDropTargetGtk4(controller); + if (target == null) return 0; + return target.dropAcceptGtk4(drop) ? 1 : 0; +} + +static long DropEnter(long controller, long drop, double x, double y) { + DropTarget target = FindDropTargetGtk4(controller); + if (target == null) return 0; + return target.dropMotionGtk4(drop, x, y, true); +} + +static long DropMotion(long controller, long drop, double x, double y) { + DropTarget target = FindDropTargetGtk4(controller); + if (target == null) return 0; + return target.dropMotionGtk4(drop, x, y, false); +} + +static void DropLeave(long controller, long drop) { + DropTarget target = FindDropTargetGtk4(controller); + if (target == null) return; + target.dropLeaveGtk4(drop); +} + +static long Drop(long controller, long drop, double x, double y) { + DropTarget target = FindDropTargetGtk4(controller); + if (target == null) return 0; + return target.dropGtk4(drop, x, y) ? 1 : 0; +} + /** * Adds the listener to the collection of listeners who will * be notified when a drag and drop operation is in progress, by sending @@ -593,12 +660,19 @@ public Transfer[] getTransfer() { void onDispose(){ if (control == null) return; - OS.g_signal_handler_disconnect(control.handle, drag_motion_handler); - OS.g_signal_handler_disconnect(control.handle, drag_leave_handler); - OS.g_signal_handler_disconnect(control.handle, drag_data_received_handler); - OS.g_signal_handler_disconnect(control.handle, drag_drop_handler); - if (transferAgents.length != 0) - GTK3.gtk_drag_dest_unset(control.handle); + if (GTK.GTK4) { + if (dropController != 0) { + GTK4.gtk_widget_remove_controller(control.handle, dropController); + dropController = 0; + } + } else { + OS.g_signal_handler_disconnect(control.handle, drag_motion_handler); + OS.g_signal_handler_disconnect(control.handle, drag_leave_handler); + OS.g_signal_handler_disconnect(control.handle, drag_data_received_handler); + OS.g_signal_handler_disconnect(control.handle, drag_drop_handler); + if (transferAgents.length != 0) + GTK3.gtk_drag_dest_unset(control.handle); + } transferAgents = null; if (controlListener != null) control.removeListener(SWT.Dispose, controlListener); @@ -609,22 +683,30 @@ void onDispose(){ int opToOsOp(int operation){ int osOperation = 0; + // GTK4 redefined the GdkDragAction values, so they differ from GTK3. + int copy = GTK.GTK4 ? GTK4.GDK_ACTION_COPY : GDK.GDK_ACTION_COPY; + int move = GTK.GTK4 ? GTK4.GDK_ACTION_MOVE : GDK.GDK_ACTION_MOVE; + int link = GTK.GTK4 ? GTK4.GDK_ACTION_LINK : GDK.GDK_ACTION_LINK; if ((operation & DND.DROP_COPY) == DND.DROP_COPY) - osOperation |= GDK.GDK_ACTION_COPY; + osOperation |= copy; if ((operation & DND.DROP_MOVE) == DND.DROP_MOVE) - osOperation |= GDK.GDK_ACTION_MOVE; + osOperation |= move; if ((operation & DND.DROP_LINK) == DND.DROP_LINK) - osOperation |= GDK.GDK_ACTION_LINK; + osOperation |= link; return osOperation; } int osOpToOp(int osOperation){ int operation = DND.DROP_NONE; - if ((osOperation & GDK.GDK_ACTION_COPY) == GDK.GDK_ACTION_COPY) + // GTK4 redefined the GdkDragAction values, so they differ from GTK3. + int copy = GTK.GTK4 ? GTK4.GDK_ACTION_COPY : GDK.GDK_ACTION_COPY; + int move = GTK.GTK4 ? GTK4.GDK_ACTION_MOVE : GDK.GDK_ACTION_MOVE; + int link = GTK.GTK4 ? GTK4.GDK_ACTION_LINK : GDK.GDK_ACTION_LINK; + if ((osOperation & copy) == copy) operation |= DND.DROP_COPY; - if ((osOperation & GDK.GDK_ACTION_MOVE) == GDK.GDK_ACTION_MOVE) + if ((osOperation & move) == move) operation |= DND.DROP_MOVE; - if ((osOperation & GDK.GDK_ACTION_LINK) == GDK.GDK_ACTION_LINK) + if ((osOperation & link) == link) operation |= DND.DROP_LINK; return operation; } @@ -825,4 +907,228 @@ void updateDragOverHover(long delay, DNDEvent event) { dragOverEvent.operations = event.operations; dragOverEvent.time = event.time; } + +/* GTK4 drop target handlers */ + +boolean dropAcceptGtk4(long drop) { + if (control == null || control.isDisposed()) return false; + long formats = GTK4.gdk_drop_get_formats(drop); + if (formats == 0) return false; + for (Transfer transfer : transferAgents) { + if (transfer == null) continue; + long gtype = ContentProviders.getInstance().getGType(transfer); + if (gtype != 0 && GTK4.gdk_content_formats_contain_gtype(formats, gtype)) { + return true; + } + } + return false; +} + +long dropMotionGtk4(long drop, double x, double y, boolean isEnter) { + int oldKeyOperation = keyOperation; + + if (isEnter) { + selectedDataType = null; + selectedOperation = DND.DROP_NONE; + } + + DNDEvent event = new DNDEvent(); + if (!setEventDataGtk4(drop, x, y, event)) { + keyOperation = -1; + return 0; + } + + int allowedOperations = event.operations; + TransferData[] allowedDataTypes = new TransferData[event.dataTypes.length]; + System.arraycopy(event.dataTypes, 0, allowedDataTypes, 0, allowedDataTypes.length); + + if (isEnter) { + event.type = DND.DragEnter; + } else if (keyOperation == oldKeyOperation) { + event.type = DND.DragOver; + event.dataType = selectedDataType; + event.detail = selectedOperation; + } else { + event.type = DND.DragOperationChanged; + event.dataType = selectedDataType; + } + updateDragOverHover(DRAGOVER_HYSTERESIS, event); + selectedDataType = null; + selectedOperation = DND.DROP_NONE; + notifyListeners(event.type, event); + if (event.detail == DND.DROP_DEFAULT) { + event.detail = (allowedOperations & DND.DROP_MOVE) != 0 ? DND.DROP_MOVE : DND.DROP_NONE; + } + if (event.dataType != null) { + for (TransferData allowedDataType : allowedDataTypes) { + if (allowedDataType.type == event.dataType.type) { + selectedDataType = event.dataType; + break; + } + } + } + if (selectedDataType != null && (allowedOperations & event.detail) != 0) { + selectedOperation = event.detail; + } + + if (isEnter) { + dragOverHeartbeat.run(); + } + return opToOsOp(selectedOperation); +} + +void dropLeaveGtk4(long drop) { + updateDragOverHover(0, null); + + if (keyOperation == -1) return; + keyOperation = -1; + + DNDEvent event = new DNDEvent(); + event.widget = this; + event.time = (int) System.currentTimeMillis(); + event.detail = DND.DROP_NONE; + notifyListeners(DND.DragLeave, event); +} + +boolean dropGtk4(long drop, double x, double y) { + // Stop the DragOver heartbeat; GTK4 does not reliably emit drag-leave after a drop. + updateDragOverHover(0, null); + + DNDEvent event = new DNDEvent(); + if (!setEventDataGtk4(drop, x, y, event)) { + keyOperation = -1; + return false; + } + keyOperation = -1; + + int allowedOperations = event.operations; + TransferData[] allowedDataTypes = new TransferData[event.dataTypes.length]; + System.arraycopy(event.dataTypes, 0, allowedDataTypes, 0, allowedDataTypes.length); + + event.dataType = selectedDataType; + event.detail = selectedOperation; + selectedDataType = null; + selectedOperation = DND.DROP_NONE; + notifyListeners(DND.DropAccept, event); + if (event.dataType != null) { + for (TransferData allowedDataType : allowedDataTypes) { + if (allowedDataType.type == event.dataType.type) { + selectedDataType = allowedDataType; + break; + } + } + } + if (selectedDataType != null && ((event.detail & allowedOperations) == event.detail)) { + selectedOperation = event.detail; + } + if (selectedOperation == DND.DROP_NONE) { + GTK4.gdk_drop_finish(drop, 0); + return false; + } + + // Find the transfer agent that supports the selected data type and request its value + Transfer selectedTransfer = null; + for (Transfer transfer : transferAgents) { + if (transfer != null && transfer.isSupportedType(selectedDataType)) { + selectedTransfer = transfer; + break; + } + } + if (selectedTransfer == null) { + GTK4.gdk_drop_finish(drop, 0); + return false; + } + + long gtype = ContentProviders.getInstance().getGType(selectedTransfer); + final TransferData dropDataType = selectedDataType; + final int dropAllowedOperations = allowedOperations; + GAsyncReadyCallbackHelper.run(new Async() { + @Override + public void async(long callback) { + GTK4.gdk_drop_read_value_async(drop, gtype, OS.G_PRIORITY_DEFAULT, 0, callback, 0); + } + @Override + public void callback(long result) { + Object object = null; + long gvalue = GTK4.gdk_drop_read_value_finish(drop, result, null); + if (gvalue != 0) { + object = ContentProviders.getInstance().getObject(gvalue); + } + + int operation = selectedOperation; + if (object == null) { + operation = DND.DROP_NONE; + } + + DNDEvent dropEvent = new DNDEvent(); + dropEvent.widget = DropTarget.this; + dropEvent.time = (int) System.currentTimeMillis(); + dropEvent.detail = operation; + dropEvent.dataType = dropDataType; + dropEvent.data = object; + operation = DND.DROP_NONE; + notifyListeners(DND.Drop, dropEvent); + if ((dropAllowedOperations & dropEvent.detail) == dropEvent.detail) { + operation = dropEvent.detail; + } + + GTK4.gdk_drop_finish(drop, opToOsOp(operation)); + } + }); + return true; +} + +boolean setEventDataGtk4(long drop, double x, double y, DNDEvent event) { + if (drop == 0) return false; + long formats = GTK4.gdk_drop_get_formats(drop); + int actions = GTK4.gdk_drop_get_actions(drop); + if (formats == 0) return false; + + // get allowed operations + int style = getStyle(); + int operations = osOpToOp(actions) & style; + if (operations == DND.DROP_NONE) return false; + + // get current operation + int operation = getOperationFromKeyState(); + keyOperation = operation; + if (operation == DND.DROP_DEFAULT) { + if ((style & DND.DROP_DEFAULT) == 0) { + operation = (operations & DND.DROP_MOVE) != 0 ? DND.DROP_MOVE : DND.DROP_NONE; + } + } else { + if ((operation & operations) == 0) operation = DND.DROP_NONE; + } + + // Get allowed transfer types + TransferData[] dataTypes = new TransferData[0]; + for (Transfer transfer : transferAgents) { + if (transfer == null) continue; + long gtype = ContentProviders.getInstance().getGType(transfer); + if (gtype == 0 || !GTK4.gdk_content_formats_contain_gtype(formats, gtype)) continue; + TransferData[] supported = transfer.getSupportedTypes(); + TransferData[] newDataTypes = new TransferData[dataTypes.length + supported.length]; + System.arraycopy(dataTypes, 0, newDataTypes, 0, dataTypes.length); + System.arraycopy(supported, 0, newDataTypes, dataTypes.length, supported.length); + dataTypes = newDataTypes; + } + if (dataTypes.length == 0) return false; + + // x and y are relative to the widget; translate to display coordinates + Point coordinates = control.toDisplay((int) x, (int) y); + + event.widget = this; + event.x = coordinates.x; + event.y = coordinates.y; + event.time = (int) System.currentTimeMillis(); + event.feedback = DND.FEEDBACK_SELECT; + event.dataTypes = dataTypes; + event.dataType = dataTypes[0]; + event.operations = operations; + event.detail = operation; + if (dropEffect != null) { + event.item = dropEffect.getItem(coordinates.x, coordinates.y); + } + return true; +} } 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 d290dcf83fb..0d22afe9502 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 @@ -359,6 +359,18 @@ JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1content_1formats_1builder_1new) } #endif +#ifndef NO_gdk_1content_1formats_1contain_1gtype +JNIEXPORT jboolean JNICALL GTK4_NATIVE(gdk_1content_1formats_1contain_1gtype) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1) +{ + jboolean rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1content_1formats_1contain_1gtype_FUNC); + rc = (jboolean)gdk_content_formats_contain_gtype((GdkContentFormats *)arg0, (GType)arg1); + GTK4_NATIVE_EXIT(env, that, gdk_1content_1formats_1contain_1gtype_FUNC); + return rc; +} +#endif + #ifndef NO_gdk_1content_1formats_1get_1gtypes JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1content_1formats_1get_1gtypes) (JNIEnv *env, jclass that, jlong arg0, jlongArray arg1) @@ -613,6 +625,66 @@ JNIEXPORT void JNICALL GTK4_NATIVE(gdk_1content_1serializer_1set_1task_1data) } #endif +#ifndef NO_gdk_1drop_1finish +JNIEXPORT void JNICALL GTK4_NATIVE(gdk_1drop_1finish) + (JNIEnv *env, jclass that, jlong arg0, jint arg1) +{ + GTK4_NATIVE_ENTER(env, that, gdk_1drop_1finish_FUNC); + gdk_drop_finish((GdkDrop *)arg0, (GdkDragAction)arg1); + GTK4_NATIVE_EXIT(env, that, gdk_1drop_1finish_FUNC); +} +#endif + +#ifndef NO_gdk_1drop_1get_1actions +JNIEXPORT jint JNICALL GTK4_NATIVE(gdk_1drop_1get_1actions) + (JNIEnv *env, jclass that, jlong arg0) +{ + jint rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1drop_1get_1actions_FUNC); + rc = (jint)gdk_drop_get_actions((GdkDrop *)arg0); + GTK4_NATIVE_EXIT(env, that, gdk_1drop_1get_1actions_FUNC); + return rc; +} +#endif + +#ifndef NO_gdk_1drop_1get_1formats +JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1drop_1get_1formats) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + GTK4_NATIVE_ENTER(env, that, gdk_1drop_1get_1formats_FUNC); + rc = (jlong)gdk_drop_get_formats((GdkDrop *)arg0); + GTK4_NATIVE_EXIT(env, that, gdk_1drop_1get_1formats_FUNC); + return rc; +} +#endif + +#ifndef NO_gdk_1drop_1read_1value_1async +JNIEXPORT void JNICALL GTK4_NATIVE(gdk_1drop_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_1drop_1read_1value_1async_FUNC); + gdk_drop_read_value_async((GdkDrop *)arg0, (GType)arg1, arg2, (GCancellable *)arg3, (GAsyncReadyCallback)arg4, (gpointer)arg5); + GTK4_NATIVE_EXIT(env, that, gdk_1drop_1read_1value_1async_FUNC); +} +#endif + +#ifndef NO_gdk_1drop_1read_1value_1finish +JNIEXPORT jlong JNICALL GTK4_NATIVE(gdk_1drop_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_1drop_1read_1value_1finish_FUNC); + if (arg2) if ((lparg2 = (*env)->GetLongArrayElements(env, arg2, NULL)) == NULL) goto fail; + rc = (jlong)gdk_drop_read_value_finish((GdkDrop *)arg0, (GAsyncResult *)arg1, (GError **)lparg2); +fail: + if (arg2 && lparg2) (*env)->ReleaseLongArrayElements(env, arg2, lparg2, 0); + GTK4_NATIVE_EXIT(env, that, gdk_1drop_1read_1value_1finish_FUNC); + return rc; +} +#endif + #ifndef NO_gdk_1paintable_1snapshot JNIEXPORT void JNICALL GTK4_NATIVE(gdk_1paintable_1snapshot) (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3) @@ -2841,6 +2913,16 @@ JNIEXPORT jlong JNICALL GTK4_NATIVE(gtk_1widget_1pick) } #endif +#ifndef NO_gtk_1widget_1remove_1controller +JNIEXPORT void JNICALL GTK4_NATIVE(gtk_1widget_1remove_1controller) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1) +{ + GTK4_NATIVE_ENTER(env, that, gtk_1widget_1remove_1controller_FUNC); + gtk_widget_remove_controller((GtkWidget *)arg0, (GtkEventController *)arg1); + GTK4_NATIVE_EXIT(env, that, gtk_1widget_1remove_1controller_FUNC); +} +#endif + #ifndef NO_gtk_1widget_1set_1cursor JNIEXPORT void JNICALL GTK4_NATIVE(gtk_1widget_1set_1cursor) (JNIEnv *env, jclass that, jlong arg0, jlong 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 15d43724ca5..6766ff954b9 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 @@ -47,6 +47,7 @@ typedef enum { gdk_1content_1formats_1builder_1add_1mime_1type_FUNC, gdk_1content_1formats_1builder_1free_1to_1formats_FUNC, gdk_1content_1formats_1builder_1new_FUNC, + gdk_1content_1formats_1contain_1gtype_FUNC, gdk_1content_1formats_1get_1gtypes_FUNC, gdk_1content_1formats_1get_1mime_1types_FUNC, gdk_1content_1formats_1to_1string_FUNC, @@ -67,6 +68,11 @@ typedef enum { gdk_1content_1serializer_1return_1error_FUNC, gdk_1content_1serializer_1return_1success_FUNC, gdk_1content_1serializer_1set_1task_1data_FUNC, + gdk_1drop_1finish_FUNC, + gdk_1drop_1get_1actions_FUNC, + gdk_1drop_1get_1formats_FUNC, + gdk_1drop_1read_1value_1async_FUNC, + gdk_1drop_1read_1value_1finish_FUNC, gdk_1paintable_1snapshot_FUNC, gdk_1toplevel_1focus_FUNC, gdk_1toplevel_1get_1state_FUNC, @@ -231,6 +237,7 @@ typedef enum { gtk_1widget_1measure_FUNC, gtk_1widget_1paintable_1new_FUNC, gtk_1widget_1pick_FUNC, + gtk_1widget_1remove_1controller_FUNC, gtk_1widget_1set_1cursor_FUNC, gtk_1widget_1set_1focusable_FUNC, gtk_1widget_1set_1overflow_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 59edf503279..aa70f5a3f23 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 @@ -383,14 +383,17 @@ public static String getEnvironmentalVariable (String envVarName) { public static final byte[] delete_text = ascii("delete-text"); public static final byte[] direction_changed = ascii("direction-changed"); public static final byte[] dpi_changed = ascii("notify::scale-factor"); + public static final byte[] accept = ascii("accept"); public static final byte[] drag_begin = ascii("drag-begin"); public static final byte[] drag_data_delete = ascii("drag-data-delete"); public static final byte[] drag_data_get = ascii("drag-data-get"); public static final byte[] drag_data_received = ascii("drag-data-received"); public static final byte[] drag_drop = ascii("drag-drop"); public static final byte[] drag_end = ascii("drag-end"); + public static final byte[] drag_enter = ascii("drag-enter"); public static final byte[] drag_leave = ascii("drag-leave"); public static final byte[] drag_motion = ascii("drag-motion"); + public static final byte[] drop = ascii("drop"); public static final byte[] prepare = ascii("prepare"); public static final byte[] draw = ascii("draw"); public static final byte[] end = ascii("end"); 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 df933e27183..ba03262b095 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 @@ -228,6 +228,36 @@ public class GTK4 { public static final native void gdk_content_formats_builder_add_mime_type(long builder, byte[] mime_type); /** @param builder cast=(GdkContentFormatsBuilder *) */ public static final native long gdk_content_formats_builder_free_to_formats(long builder); + /** + * @param formats cast=(GdkContentFormats *) + * @param type cast=(GType) + */ + public static final native boolean gdk_content_formats_contain_gtype(long formats, long type); + + /* GdkDrop */ + /** + * @param drop cast=(GdkDrop *) + * @param action cast=(GdkDragAction) + */ + public static final native void gdk_drop_finish(long drop, int action); + /** @param drop cast=(GdkDrop *) */ + public static final native int gdk_drop_get_actions(long drop); + /** @param drop cast=(GdkDrop *) */ + public static final native long gdk_drop_get_formats(long drop); + /** + * @param drop cast=(GdkDrop *) + * @param type cast=(GType) + * @param cancellable cast=(GCancellable *) + * @param callback cast=(GAsyncReadyCallback) + * @param user_data cast=(gpointer) + */ + public static final native void gdk_drop_read_value_async(long drop, long type, int io_priority, long cancellable, long callback, long user_data); + /** + * @param drop cast=(GdkDrop *) + * @param result cast=(GAsyncResult *) + * @param error cast=(GError **) + */ + public static final native long gdk_drop_read_value_finish(long drop, long result, long[] error); /* GtkFileChooser */ /** @@ -705,6 +735,11 @@ public class GTK4 { * @param controller cast=(GtkEventController *) */ public static final native void gtk_widget_add_controller(long widget, long controller); + /** + * @param widget cast=(GtkWidget *) + * @param controller cast=(GtkEventController *) + */ + public static final native void gtk_widget_remove_controller(long widget, long controller); /** @param widget cast=(GtkWidget *) */ public static final native long gtk_widget_get_first_child(long widget); /** @param widget cast=(GtkWidget *) */