Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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.*;
Expand All @@ -39,15 +38,24 @@ public class Clipboard {

static long GTKCLIPBOARD;
static long GTKPRIMARYCLIPBOARD;
/**
* GTK3 only
*/
private static long TARGET;

static {
GTKCLIPBOARD = GTK.GTK4 ? GDK.gdk_display_get_clipboard(GDK.gdk_display_get_default()) : GTK3.gtk_clipboard_get (GDK.GDK_NONE);
byte[] buffer = Converter.wcsToMbcs("PRIMARY", true);
long primary = GTK.GTK4 ? 0 : GDK.gdk_atom_intern(buffer, false);
GTKPRIMARYCLIPBOARD = GTK.GTK4 ? GDK.gdk_display_get_primary_clipboard(GDK.gdk_display_get_default()) : GTK3.gtk_clipboard_get(primary);
buffer = Converter.wcsToMbcs("TARGETS", true);
TARGET = GTK.GTK4 ? 0 : GDK.gdk_atom_intern(buffer, false);
if (GTK.GTK4) {
GTKCLIPBOARD = GDK.gdk_display_get_clipboard(GDK.gdk_display_get_default());
GTKPRIMARYCLIPBOARD = GDK.gdk_display_get_primary_clipboard(GDK.gdk_display_get_default());
TARGET = 0;
} else {
GTKCLIPBOARD = GTK3.gtk_clipboard_get(GDK.GDK_NONE);
byte[] buffer = Converter.wcsToMbcs("PRIMARY", true);
long primary = GDK.gdk_atom_intern(buffer, false);
GTKPRIMARYCLIPBOARD = GTK3.gtk_clipboard_get(primary);
buffer = Converter.wcsToMbcs("TARGETS", true);
TARGET = GDK.gdk_atom_intern(buffer, false);
}
}

/**
Expand Down Expand Up @@ -188,8 +196,13 @@ public void clearContents() {
*/
public void clearContents(int clipboards) {
checkWidget();
ClipboardProxy proxy = ClipboardProxy._getInstance(display);
proxy.clear(this, clipboards);
if (GTK.GTK4) {
ClipboardProxyGTK4 proxy = ClipboardProxyGTK4._getInstance(display);
proxy.clear(this, clipboards);
} else {
ClipboardProxy proxy = ClipboardProxy._getInstance(display);
proxy.clear(this, clipboards);
}
}

/**
Expand Down Expand Up @@ -290,14 +303,12 @@ public Object getContents(Transfer transfer) {
* @since 3.1
*/
public Object getContents(Transfer transfer, int clipboards) {
checkWidget();
if (transfer == null) DND.error(SWT.ERROR_NULL_ARGUMENT);

if(GTK.GTK4) {
Object result = getContents_gtk4(transfer, clipboards);
return result;
if (GTK.GTK4) {
return getContents_gtk4(transfer, clipboards);
}

checkWidget();
if (transfer == null) DND.error(SWT.ERROR_NULL_ARGUMENT);
long selection_data = 0;
int[] typeIds = transfer.getTypeIds();
boolean textTransfer = transfer.getTypeNames()[0].equals("UTF8_STRING");
Expand Down Expand Up @@ -327,65 +338,11 @@ public Object getContents(Transfer transfer, int clipboards) {
}

private Object getContents_gtk4(Transfer transfer, int clipboards) {
checkWidget();
if (transfer == null) DND.error(SWT.ERROR_NULL_ARGUMENT);

long contents = GTK4.gdk_clipboard_get_content(Clipboard.GTKCLIPBOARD);
if(contents == 0) return null;
long value = OS.g_malloc (OS.GValue_sizeof ());
C.memset (value, 0, OS.GValue_sizeof ());

//Pasting of text (TextTransfer/RTFTransfer)
if(transfer.getTypeNames()[0].equals("text/plain") || transfer.getTypeNames()[0].equals("text/rtf")) {
OS.g_value_init(value, OS.G_TYPE_STRING());
if (!GTK4.gdk_content_provider_get_value (contents, value, null)) return null;
long cStr = OS.g_value_get_string(value);
long [] items_written = new long [1];
long utf16Ptr = OS.g_utf8_to_utf16(cStr, -1, null, items_written, null);
OS.g_free(cStr);
if (utf16Ptr == 0) return null;
int length = (int)items_written[0];
char[] buffer = new char[length];
C.memmove(buffer, utf16Ptr, length * 2);
OS.g_free(utf16Ptr);
String str = new String(buffer);
if(transfer.getTypeNames()[0].equals("text/rtf") && !str.contains("{\\rtf1")) {
return null;
}
if(transfer.getTypeNames()[0].equals("text/plain") && str.contains("{\\rtf1")){
return null;
}
return str;
}
//Pasting of Image
if(transfer.getTypeIds()[0] == (int)GDK.GDK_TYPE_PIXBUF()) {
ImageData imgData = null;
OS.g_value_init(value, GDK.GDK_TYPE_PIXBUF());
if (!GTK4.gdk_content_provider_get_value (contents, value, null)) return null;
long pixbufObj = OS.g_value_get_object(value);
if (pixbufObj != 0) {
Image img = Image.gtk_new_from_pixbuf(Display.getCurrent(), SWT.BITMAP, pixbufObj);
imgData = img.getImageData();
img.dispose();
}
return imgData;
}
//Pasting of HTML
if(transfer.getTypeNames()[0].equals("text/html")) {
OS.g_value_init(value, OS.G_TYPE_STRING());
if (!GTK4.gdk_content_provider_get_value (contents, value, null)) return null;
long cStr = OS.g_value_get_string(value);
long [] items_written = new long [1];
long utf16Ptr = OS.g_utf8_to_utf16(cStr, -1, null, items_written, null);
OS.g_free(cStr);
if (utf16Ptr == 0) return null;
int length = (int)items_written[0];
char[] buffer = new char[length];
C.memmove(buffer, utf16Ptr, length * 2);
OS.g_free(utf16Ptr);
String str = new String(buffer);
return str;
}
//TODO: [GTK4] Other cases
return null;
ClipboardProxyGTK4 proxy = ClipboardProxyGTK4._getInstance(display);
return proxy.getData(this, transfer, clipboards);
}

/**
Expand Down Expand Up @@ -525,9 +482,16 @@ public void setContents(Object[] data, Transfer[] dataTypes, int clipboards) {
DND.error(SWT.ERROR_INVALID_ARGUMENT);
}
}
ClipboardProxy proxy = ClipboardProxy._getInstance(display);
if (!proxy.setData(this, data, dataTypes, clipboards)) {
DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD);
if (GTK.GTK4) {
ClipboardProxyGTK4 proxy = ClipboardProxyGTK4._getInstance(display);
if (!proxy.setData(this, data, dataTypes, clipboards)) {
DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD);
}
} else {
ClipboardProxy proxy = ClipboardProxy._getInstance(display);
if (!proxy.setData(this, data, dataTypes, clipboards)) {
DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD);
}
}
}

Expand Down Expand Up @@ -623,8 +587,10 @@ public TransferData[] getAvailableTypes(int clipboards) {
public String[] getAvailableTypeNames() {
checkWidget();
if(GTK.GTK4) {
// TODO make sure this code works with new GTK4 impl
long formatsCStr = GTK4.gdk_content_formats_to_string(GTK4.gdk_clipboard_get_formats(Clipboard.GTKCLIPBOARD));
String formatsStr = Converter.cCharPtrToJavaString(formatsCStr, true);
System.out.println(formatsStr);
String[] types = formatsStr.split(" ");
return types;
}
Expand Down Expand Up @@ -673,6 +639,7 @@ private int[] getAvailableClipboardTypes () {
return gtk3_getAvailableTypes(GTKCLIPBOARD);
}

// TODO make sure this code works with new GTK4 impl
private int[] gtk4_getAvailableTypes(long clipboard) {
long formats = GTK4.gdk_clipboard_get_formats(clipboard);
long[] n_gtypes = new long[1];
Expand Down Expand Up @@ -723,4 +690,6 @@ long gtk_clipboard_wait_for_contents(long clipboard, long target) {
}
return selection_data;
}


}
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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.
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -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$
Expand All @@ -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){
Expand All @@ -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();
Expand All @@ -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;
}
Expand Down Expand Up @@ -148,9 +144,6 @@ long getFunc(long clipboard, long selection_data, long info, long user_data_or_o
}

boolean setData(Clipboard owner, Object[] data, Transfer[] dataTypes, int clipboards) {

if(GTK.GTK4) return setData_gtk4(owner, data, dataTypes, clipboards);

GtkTargetEntry[] entries = new GtkTargetEntry [0];
long pTargetsList = 0;
try {
Expand Down Expand Up @@ -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;
}
}
Loading
Loading