1 /******************************************************************************* 2 * Copyright (c) 2000, 2005 IBM Corporation and others. 3 * All rights reserved. This program and the accompanying materials 4 * are made available under the terms of the Eclipse Public License v1.0 5 * which accompanies this distribution, and is available at 6 * http://www.eclipse.org/legal/epl-v10.html 7 * 8 * Contributors: 9 * IBM Corporation - initial API and implementation 10 * Port to the D programming language: 11 * Frank Benoit <benoit@tionex.de> 12 *******************************************************************************/ 13 module org.eclipse.swt.dnd.ClipboardProxy; 14 15 import java.lang.all; 16 17 18 19 import org.eclipse.swt.SWT; 20 import org.eclipse.swt.internal.gtk.OS; 21 import org.eclipse.swt.widgets.Display; 22 import org.eclipse.swt.widgets.Event; 23 import org.eclipse.swt.widgets.Listener; 24 import org.eclipse.swt.dnd.Transfer; 25 import org.eclipse.swt.dnd.Clipboard; 26 import org.eclipse.swt.dnd.DND; 27 import org.eclipse.swt.dnd.TransferData; 28 29 version(Tango){ 30 static import tango.stdc..string; 31 } else { // Phobos 32 } 33 34 35 class ClipboardProxy { 36 /* Data is not flushed to the clipboard immediately. 37 * This class will remember the data and provide it when requested. 38 */ 39 Object[] clipboardData; 40 Transfer[] clipboardDataTypes; 41 Object[] primaryClipboardData; 42 Transfer[] primaryClipboardDataTypes; 43 44 Display display; 45 Clipboard activeClipboard = null; 46 Clipboard activePrimaryClipboard = null; 47 48 static String ID = "CLIPBOARD PROXY OBJECT"; //$NON-NLS-1$ 49 50 static ClipboardProxy _getInstance(Display display) { 51 ClipboardProxy proxy = cast(ClipboardProxy) display.getData(ID); 52 if (proxy !is null) return proxy; 53 proxy = new ClipboardProxy(display); 54 display.setData(ID, proxy); 55 display.addListener(SWT.Dispose, new class( display ) Listener { 56 Display disp; 57 this( Display disp ){ this.disp = disp; } 58 public void handleEvent(Event event) { 59 ClipboardProxy clipbordProxy = cast(ClipboardProxy)disp.getData(ID); 60 if (clipbordProxy is null) return; 61 disp.setData(ID, null); 62 clipbordProxy.dispose(); 63 } 64 }); 65 return proxy; 66 } 67 68 this(Display display) { 69 this.display = display; 70 } 71 72 void clear (Clipboard owner, int clipboards) { 73 if ((clipboards & DND.CLIPBOARD) !is 0 && activeClipboard is owner) { 74 OS.gtk_clipboard_clear(Clipboard.GTKCLIPBOARD); 75 } 76 if ((clipboards & DND.SELECTION_CLIPBOARD) !is 0 && activePrimaryClipboard is owner) { 77 OS.gtk_clipboard_clear(Clipboard.GTKPRIMARYCLIPBOARD); 78 } 79 } 80 81 private static extern(C) void clearFuncFunc(GtkClipboard *clipboard, void* user_data_or_owner){ 82 auto obj = cast(ClipboardProxy)user_data_or_owner; 83 obj.clearFunc( clipboard ); 84 } 85 void clearFunc(GtkClipboard *clipboard ){ 86 if (clipboard is Clipboard.GTKCLIPBOARD) { 87 activeClipboard = null; 88 clipboardData = null; 89 clipboardDataTypes = null; 90 } 91 if (clipboard is Clipboard.GTKPRIMARYCLIPBOARD) { 92 activePrimaryClipboard = null; 93 primaryClipboardData = null; 94 primaryClipboardDataTypes = null; 95 } 96 } 97 98 void dispose () { 99 if (display is null) return; 100 if (activeClipboard !is null) OS.gtk_clipboard_clear(Clipboard.GTKCLIPBOARD); 101 if (activePrimaryClipboard !is null) OS.gtk_clipboard_clear(Clipboard.GTKPRIMARYCLIPBOARD); 102 display = null; 103 clipboardData = null; 104 clipboardDataTypes = null; 105 primaryClipboardData = null; 106 primaryClipboardDataTypes = null; 107 } 108 109 private static extern(C) void getFuncFunc( 110 GtkClipboard *clipboard, 111 GtkSelectionData *selection_data, 112 uint info, 113 void* user_data_or_owner) 114 { 115 auto obj = cast(ClipboardProxy)user_data_or_owner; 116 obj.getFunc( clipboard, selection_data, info ); 117 } 118 /** 119 * This function provides the data to the clipboard on request. 120 * When this clipboard is disposed, the data will no longer be available. 121 */ 122 int getFunc( 123 GtkClipboard *clipboard, 124 GtkSelectionData *selectionData, 125 uint info) 126 { 127 if (selectionData is null) return 0; 128 TransferData tdata = new TransferData(); 129 tdata.type = selectionData.target; 130 Transfer[] types = (clipboard is Clipboard.GTKCLIPBOARD) ? clipboardDataTypes : primaryClipboardDataTypes; 131 ptrdiff_t index = -1; 132 for (int i = 0; i < types.length; i++) { 133 if (types[i].isSupportedType(tdata)) { 134 index = i; 135 break; 136 } 137 } 138 if (index is -1) return 0; 139 Object[] data = (clipboard is Clipboard.GTKCLIPBOARD) ? clipboardData : primaryClipboardData; 140 types[index].javaToNative(data[index], tdata); 141 if (tdata.format < 8 || tdata.format % 8 !is 0) { 142 return 0; 143 } 144 OS.gtk_selection_data_set(selectionData, tdata.type, tdata.format, tdata.pValue, tdata.length); 145 OS.g_free(tdata.pValue); 146 return 1; 147 } 148 149 bool setData(Clipboard owner, Object[] data, Transfer[] dataTypes, int clipboards) { 150 GtkTargetEntry*[] entries; 151 GtkTargetEntry* pTargetsList; 152 try { 153 for (int i = 0; i < dataTypes.length; i++) { 154 Transfer transfer = dataTypes[i]; 155 int[] typeIds = transfer.getTypeIds(); 156 String[] typeNames = transfer.getTypeNames(); 157 for (int j = 0; j < typeIds.length; j++) { 158 GtkTargetEntry* entry = new GtkTargetEntry(); 159 entry.info = typeIds[j]; 160 char* pName = cast(char*) 161 OS.g_malloc(typeNames[j].length+1); 162 pName[ 0 .. typeNames[j].length ] = typeNames[j]; 163 pName[ typeNames[j].length ] = '\0'; 164 entry.target = pName; 165 GtkTargetEntry*[] tmp = new GtkTargetEntry*[entries.length + 1]; 166 SimpleType!(GtkTargetEntry*) 167 .arraycopy(entries, 0, tmp, 0, entries.length); 168 tmp[entries.length] = entry; 169 entries = tmp; 170 } 171 } 172 173 pTargetsList = cast(GtkTargetEntry*) 174 OS.g_malloc(GtkTargetEntry.sizeof * entries.length); 175 int offset = 0; 176 for (int i = 0; i < entries.length; i++) { 177 OS.memmove(pTargetsList + i, entries[i], GtkTargetEntry.sizeof); 178 offset += GtkTargetEntry.sizeof; 179 } 180 if ((clipboards & DND.CLIPBOARD) !is 0) { 181 if (activeClipboard !is null) OS.gtk_clipboard_clear(Clipboard.GTKCLIPBOARD); 182 clipboardData = data; 183 clipboardDataTypes = dataTypes; 184 if (!OS.gtk_clipboard_set_with_data(Clipboard.GTKCLIPBOARD, 185 pTargetsList, cast(int)/*64bit*/entries.length, &getFuncFunc, 186 &clearFuncFunc, cast(void*)this )) { 187 return false; 188 } 189 activeClipboard = owner; 190 } 191 if ((clipboards & DND.SELECTION_CLIPBOARD) !is 0) { 192 if (activePrimaryClipboard !is null) OS.gtk_clipboard_clear(Clipboard.GTKPRIMARYCLIPBOARD); 193 primaryClipboardData = data; 194 primaryClipboardDataTypes = dataTypes; 195 if (!OS.gtk_clipboard_set_with_data(Clipboard.GTKPRIMARYCLIPBOARD, 196 pTargetsList, cast(int)/*64bit*/entries.length, &getFuncFunc, 197 &clearFuncFunc, cast(void*)this )) { 198 return false; 199 } 200 activePrimaryClipboard = owner; 201 } 202 } finally { 203 for (int i = 0; i < entries.length; i++) { 204 GtkTargetEntry* entry = entries[i]; 205 if( entry.target !is null) OS.g_free(entry.target); 206 } 207 if (pTargetsList !is null) OS.g_free(pTargetsList); 208 } 209 210 return true; 211 } 212 }