1 /******************************************************************************* 2 * Copyright (c) 2000, 2008 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.Clipboard; 14 15 16 17 import org.eclipse.swt.SWT; 18 import org.eclipse.swt.SWTError; 19 import org.eclipse.swt.SWTException; 20 import org.eclipse.swt.internal.Converter; 21 import org.eclipse.swt.internal.gtk.OS; 22 import org.eclipse.swt.widgets.Display; 23 import org.eclipse.swt.dnd.Transfer; 24 import org.eclipse.swt.dnd.TransferData; 25 import org.eclipse.swt.dnd.DND; 26 import org.eclipse.swt.dnd.ClipboardProxy; 27 28 import java.lang.all; 29 30 import java.lang.Thread; 31 version(Tango){ 32 static import tango.stdc..string; 33 } else { // Phobos 34 } 35 36 /** 37 * The <code>Clipboard</code> provides a mechanism for transferring data from one 38 * application to another or within an application. 39 * 40 * <p>IMPORTANT: This class is <em>not</em> intended to be subclassed.</p> 41 * 42 * @see <a href="http://www.eclipse.org/swt/snippets/#clipboard">Clipboard snippets</a> 43 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ClipboardExample</a> 44 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> 45 */ 46 public class Clipboard { 47 48 private Display display; 49 50 static void* GTKCLIPBOARD; 51 static void* GTKPRIMARYCLIPBOARD; 52 private static void* TARGET; 53 private static bool static_this_completed = false; 54 private static void static_this(){ 55 if( !static_this_completed ){ 56 GTKCLIPBOARD = OS.gtk_clipboard_get( cast(void*)OS.GDK_NONE); 57 auto primary = OS.gdk_atom_intern("PRIMARY".ptr, false); 58 GTKPRIMARYCLIPBOARD = OS.gtk_clipboard_get(primary); 59 TARGET = OS.gdk_atom_intern("TARGETS".ptr, false); 60 static_this_completed = true; 61 } 62 } 63 64 /** 65 * Constructs a new instance of this class. Creating an instance of a Clipboard 66 * may cause system resources to be allocated depending on the platform. It is therefore 67 * mandatory that the Clipboard instance be disposed when no longer required. 68 * 69 * @param display the display on which to allocate the clipboard 70 * 71 * @exception SWTException <ul> 72 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> 73 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> 74 * </ul> 75 * 76 * @see Clipboard#dispose 77 * @see Clipboard#checkSubclass 78 */ 79 public this(Display display) { 80 checkSubclass (); 81 static_this(); 82 if (display is null) { 83 display = Display.getCurrent(); 84 if (display is null) { 85 display = Display.getDefault(); 86 } 87 } 88 if (display.getThread() !is Thread.currentThread()) { 89 DND.error(SWT.ERROR_THREAD_INVALID_ACCESS); 90 } 91 this.display = display; 92 } 93 94 /** 95 * Checks that this class can be subclassed. 96 * <p> 97 * The SWT class library is intended to be subclassed 98 * only at specific, controlled points. This method enforces this 99 * rule unless it is overridden. 100 * </p><p> 101 * <em>IMPORTANT:</em> By providing an implementation of this 102 * method that allows a subclass of a class which does not 103 * normally allow subclassing to be created, the implementer 104 * agrees to be fully responsible for the fact that any such 105 * subclass will likely fail between SWT releases and will be 106 * strongly platform specific. No support is provided for 107 * user-written classes which are implemented in this fashion. 108 * </p><p> 109 * The ability to subclass outside of the allowed SWT classes 110 * is intended purely to enable those not on the SWT development 111 * team to implement patches in order to get around specific 112 * limitations in advance of when those limitations can be 113 * addressed by the team. Subclassing should not be attempted 114 * without an intimate and detailed understanding of the hierarchy. 115 * </p> 116 * 117 * @exception SWTException <ul> 118 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> 119 * </ul> 120 */ 121 protected void checkSubclass () { 122 String name = this.classinfo.name; 123 String validName = Clipboard.classinfo.name; 124 if ( validName !=/*eq*/ name ) { 125 DND.error (SWT.ERROR_INVALID_SUBCLASS); 126 } 127 } 128 /** 129 * Throws an <code>SWTException</code> if the receiver can not 130 * be accessed by the caller. This may include both checks on 131 * the state of the receiver and more generally on the entire 132 * execution context. This method <em>should</em> be called by 133 * widget implementors to enforce the standard SWT invariants. 134 * <p> 135 * Currently, it is an error to invoke any method (other than 136 * <code>isDisposed()</code>) on a widget that has had its 137 * <code>dispose()</code> method called. It is also an error 138 * to call widget methods from any thread that is different 139 * from the thread that created the widget. 140 * </p><p> 141 * In future releases of SWT, there may be more or fewer error 142 * checks and exceptions may be thrown for different reasons. 143 * </p> 144 * 145 * @exception SWTException <ul> 146 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 147 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 148 * </ul> 149 */ 150 protected void checkWidget () { 151 Display display = this.display; 152 if (display is null) DND.error (SWT.ERROR_WIDGET_DISPOSED); 153 if (display.getThread() !is Thread.currentThread ()) DND.error (SWT.ERROR_THREAD_INVALID_ACCESS); 154 if (display.isDisposed()) DND.error(SWT.ERROR_WIDGET_DISPOSED); 155 } 156 157 /** 158 * If this clipboard is currently the owner of the data on the system clipboard, 159 * clear the contents. If this clipboard is not the owner, then nothing is done. 160 * Note that there are clipboard assistant applications that take ownership of 161 * data or make copies of data when it is placed on the clipboard. In these 162 * cases, it may not be possible to clear the clipboard. 163 * 164 * @exception SWTException <ul> 165 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 166 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 167 * </ul> 168 * 169 * @since 3.1 170 */ 171 public void clearContents() { 172 clearContents(DND.CLIPBOARD); 173 } 174 175 /** 176 * If this clipboard is currently the owner of the data on the specified 177 * clipboard, clear the contents. If this clipboard is not the owner, then 178 * nothing is done. 179 * 180 * <p>Note that there are clipboard assistant applications that take ownership 181 * of data or make copies of data when it is placed on the clipboard. In these 182 * cases, it may not be possible to clear the clipboard.</p> 183 * 184 * <p>The clipboards value is either one of the clipboard constants defined in 185 * class <code>DND</code>, or must be built by <em>bitwise OR</em>'ing together 186 * (that is, using the <code>int</code> "|" operator) two or more 187 * of those <code>DND</code> clipboard constants.</p> 188 * 189 * @param clipboards to be cleared 190 * 191 * @exception SWTException <ul> 192 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 193 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 194 * </ul> 195 * 196 * @see DND#CLIPBOARD 197 * @see DND#SELECTION_CLIPBOARD 198 * 199 * @since 3.1 200 */ 201 public void clearContents(int clipboards) { 202 checkWidget(); 203 ClipboardProxy proxy = ClipboardProxy._getInstance(display); 204 proxy.clear(this, clipboards); 205 } 206 207 /** 208 * Disposes of the operating system resources associated with the clipboard. 209 * The data will still be available on the system clipboard after the dispose 210 * method is called. 211 * 212 * <p>NOTE: On some platforms the data will not be available once the application 213 * has exited or the display has been disposed.</p> 214 * 215 * @exception SWTException <ul> 216 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> 217 * </ul> 218 */ 219 public void dispose () { 220 if (isDisposed()) return; 221 if (display.getThread() !is Thread.currentThread()) DND.error(SWT.ERROR_THREAD_INVALID_ACCESS); 222 display = null; 223 } 224 225 /** 226 * Retrieve the data of the specified type currently available on the system 227 * clipboard. Refer to the specific subclass of <code>Transfer</code> to 228 * determine the type of object returned. 229 * 230 * <p>The following snippet shows text and RTF text being retrieved from the 231 * clipboard:</p> 232 * 233 * <code><pre> 234 * Clipboard clipboard = new Clipboard(display); 235 * TextTransfer textTransfer = TextTransfer.getInstance(); 236 * String textData = (String)clipboard.getContents(textTransfer); 237 * if (textData !is null) System.out.println("Text is "+textData); 238 * RTFTransfer rtfTransfer = RTFTransfer.getInstance(); 239 * String rtfData = (String)clipboard.getContents(rtfTransfer); 240 * if (rtfData !is null) System.out.println("RTF Text is "+rtfData); 241 * clipboard.dispose(); 242 * </code></pre> 243 * 244 * @param transfer the transfer agent for the type of data being requested 245 * @return the data obtained from the clipboard or null if no data of this type is available 246 * 247 * @exception SWTException <ul> 248 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 249 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 250 * </ul> 251 * @exception IllegalArgumentException <ul> 252 * <li>ERROR_NULL_ARGUMENT - if transfer is null</li> 253 * </ul> 254 * 255 * @see Transfer 256 */ 257 public Object getContents(Transfer transfer) { 258 return getContents(transfer, DND.CLIPBOARD); 259 } 260 261 /** 262 * Retrieve the data of the specified type currently available on the specified 263 * clipboard. Refer to the specific subclass of <code>Transfer</code> to 264 * determine the type of object returned. 265 * 266 * <p>The following snippet shows text and RTF text being retrieved from the 267 * clipboard:</p> 268 * 269 * <code><pre> 270 * Clipboard clipboard = new Clipboard(display); 271 * TextTransfer textTransfer = TextTransfer.getInstance(); 272 * String textData = (String)clipboard.getContents(textTransfer); 273 * if (textData !is null) System.out.println("Text is "+textData); 274 * RTFTransfer rtfTransfer = RTFTransfer.getInstance(); 275 * String rtfData = (String)clipboard.getContents(rtfTransfer, DND.CLIPBOARD); 276 * if (rtfData !is null) System.out.println("RTF Text is "+rtfData); 277 * clipboard.dispose(); 278 * </code></pre> 279 * 280 * <p>The clipboards value is either one of the clipboard constants defined in 281 * class <code>DND</code>, or must be built by <em>bitwise OR</em>'ing together 282 * (that is, using the <code>int</code> "|" operator) two or more 283 * of those <code>DND</code> clipboard constants.</p> 284 * 285 * @param transfer the transfer agent for the type of data being requested 286 * @param clipboards on which to look for data 287 * 288 * @return the data obtained from the clipboard or null if no data of this type is available 289 * 290 * @exception SWTException <ul> 291 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 292 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 293 * </ul> 294 * @exception IllegalArgumentException <ul> 295 * <li>ERROR_NULL_ARGUMENT - if transfer is null</li> 296 * </ul> 297 * 298 * @see Transfer 299 * @see DND#CLIPBOARD 300 * @see DND#SELECTION_CLIPBOARD 301 * 302 * @since 3.1 303 */ 304 public Object getContents(Transfer transfer, int clipboards) { 305 checkWidget(); 306 if (transfer is null) DND.error(SWT.ERROR_NULL_ARGUMENT); 307 GtkSelectionData* selection_data; 308 auto typeIds = transfer.getTypeIds(); 309 for (int i = 0; i < typeIds.length; i++) { 310 if ((clipboards & DND.CLIPBOARD) !is 0) { 311 selection_data = gtk_clipboard_wait_for_contents(GTKCLIPBOARD, cast(void*)typeIds[i]); 312 } 313 if (selection_data !is null) break; 314 if ((clipboards & DND.SELECTION_CLIPBOARD) !is 0) { 315 selection_data = gtk_clipboard_wait_for_contents(GTKPRIMARYCLIPBOARD, cast(void*)typeIds[i]); 316 } 317 } 318 if (selection_data is null) return null; 319 GtkSelectionData* gtkSelectionData = selection_data; 320 TransferData tdata = new TransferData(); 321 tdata.type = gtkSelectionData.type; 322 tdata.pValue = gtkSelectionData.data; 323 tdata.length = gtkSelectionData.length; 324 tdata.format = gtkSelectionData.format; 325 Object result = transfer.nativeToJava(tdata); 326 OS.gtk_selection_data_free(selection_data); 327 return result; 328 } 329 330 /** 331 * Returns <code>true</code> if the clipboard has been disposed, 332 * and <code>false</code> otherwise. 333 * <p> 334 * This method gets the dispose state for the clipboard. 335 * When a clipboard has been disposed, it is an error to 336 * invoke any other method using the clipboard. 337 * </p> 338 * 339 * @return <code>true</code> when the widget is disposed and <code>false</code> otherwise 340 * 341 * @since 3.0 342 */ 343 public bool isDisposed () { 344 return (display is null); 345 } 346 347 /** 348 * Place data of the specified type on the system clipboard. More than one type 349 * of data can be placed on the system clipboard at the same time. Setting the 350 * data clears any previous data from the system clipboard, regardless of type. 351 * 352 * <p>NOTE: On some platforms, the data is immediately copied to the system 353 * clipboard but on other platforms it is provided upon request. As a result, 354 * if the application modifies the data object it has set on the clipboard, that 355 * modification may or may not be available when the data is subsequently 356 * requested.</p> 357 * 358 * <p>The following snippet shows text and RTF text being set on the copy/paste 359 * clipboard: 360 * </p> 361 * 362 * <code><pre> 363 * Clipboard clipboard = new Clipboard(display); 364 * String textData = "Hello World"; 365 * String rtfData = "{\\rtf1\\b\\i Hello World}"; 366 * TextTransfer textTransfer = TextTransfer.getInstance(); 367 * RTFTransfer rtfTransfer = RTFTransfer.getInstance(); 368 * Transfer[] transfers = new Transfer[]{textTransfer, rtfTransfer}; 369 * Object[] data = new Object[]{textData, rtfData}; 370 * clipboard.setContents(data, transfers); 371 * clipboard.dispose(); 372 * </code></pre> 373 * 374 * @param data the data to be set in the clipboard 375 * @param dataTypes the transfer agents that will convert the data to its 376 * platform specific format; each entry in the data array must have a 377 * corresponding dataType 378 * 379 * @exception IllegalArgumentException <ul> 380 * <li>ERROR_INVALID_ARGUMENT - if data is null or datatypes is null 381 * or the length of data is not the same as the length of dataTypes</li> 382 * </ul> 383 * @exception SWTException <ul> 384 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 385 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 386 * </ul> 387 * @exception SWTError <ul> 388 * <li>ERROR_CANNOT_SET_CLIPBOARD - if the clipboard is locked or otherwise unavailable</li> 389 * </ul> 390 * 391 * <p>NOTE: ERROR_CANNOT_SET_CLIPBOARD should be an SWTException, since it is a 392 * recoverable error, but can not be changed due to backward compatibility.</p> 393 */ 394 public void setContents(Object[] data, Transfer[] dataTypes) { 395 setContents(data, dataTypes, DND.CLIPBOARD); 396 } 397 398 /** 399 * Place data of the specified type on the specified clipboard. More than one 400 * type of data can be placed on the specified clipboard at the same time. 401 * Setting the data clears any previous data from the specified 402 * clipboard, regardless of type. 403 * 404 * <p>NOTE: On some platforms, the data is immediately copied to the specified 405 * clipboard but on other platforms it is provided upon request. As a result, 406 * if the application modifies the data object it has set on the clipboard, that 407 * modification may or may not be available when the data is subsequently 408 * requested.</p> 409 * 410 * <p>The clipboards value is either one of the clipboard constants defined in 411 * class <code>DND</code>, or must be built by <em>bitwise OR</em>'ing together 412 * (that is, using the <code>int</code> "|" operator) two or more 413 * of those <code>DND</code> clipboard constants.</p> 414 * 415 * <p>The following snippet shows text and RTF text being set on the copy/paste 416 * clipboard: 417 * </p> 418 * 419 * <code><pre> 420 * Clipboard clipboard = new Clipboard(display); 421 * String textData = "Hello World"; 422 * String rtfData = "{\\rtf1\\b\\i Hello World}"; 423 * TextTransfer textTransfer = TextTransfer.getInstance(); 424 * RTFTransfer rtfTransfer = RTFTransfer.getInstance(); 425 * Transfer[] transfers = new Transfer[]{textTransfer, rtfTransfer}; 426 * Object[] data = new Object[]{textData, rtfData}; 427 * clipboard.setContents(data, transfers, DND.CLIPBOARD); 428 * clipboard.dispose(); 429 * </code></pre> 430 * 431 * @param data the data to be set in the clipboard 432 * @param dataTypes the transfer agents that will convert the data to its 433 * platform specific format; each entry in the data array must have a 434 * corresponding dataType 435 * @param clipboards on which to set the data 436 * 437 * @exception IllegalArgumentException <ul> 438 * <li>ERROR_INVALID_ARGUMENT - if data is null or datatypes is null 439 * or the length of data is not the same as the length of dataTypes</li> 440 * </ul> 441 * @exception SWTException <ul> 442 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 443 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 444 * </ul> 445 * @exception SWTError <ul> 446 * <li>ERROR_CANNOT_SET_CLIPBOARD - if the clipboard is locked or otherwise unavailable</li> 447 * </ul> 448 * 449 * <p>NOTE: ERROR_CANNOT_SET_CLIPBOARD should be an SWTException, since it is a 450 * recoverable error, but can not be changed due to backward compatibility.</p> 451 * 452 * @see DND#CLIPBOARD 453 * @see DND#SELECTION_CLIPBOARD 454 * 455 * @since 3.1 456 */ 457 public void setContents(Object[] data, Transfer[] dataTypes, int clipboards) { 458 checkWidget(); 459 if (data is null || dataTypes is null || data.length !is dataTypes.length || data.length is 0) { 460 DND.error(SWT.ERROR_INVALID_ARGUMENT); 461 } 462 for (int i = 0; i < data.length; i++) { 463 if (data[i] is null || dataTypes[i] is null || !dataTypes[i].validate(data[i])) { 464 DND.error(SWT.ERROR_INVALID_ARGUMENT); 465 } 466 } 467 ClipboardProxy proxy = ClipboardProxy._getInstance(display); 468 if (!proxy.setData(this, data, dataTypes, clipboards)) { 469 DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD); 470 } 471 } 472 473 /** 474 * Returns an array of the data types currently available on the system 475 * clipboard. Use with Transfer.isSupportedType. 476 * 477 * @return array of data types currently available on the system clipboard 478 * 479 * @exception SWTException <ul> 480 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 481 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 482 * </ul> 483 * 484 * @see Transfer#isSupportedType 485 * 486 * @since 3.0 487 */ 488 public TransferData[] getAvailableTypes() { 489 return getAvailableTypes(DND.CLIPBOARD); 490 } 491 492 /** 493 * Returns an array of the data types currently available on the specified 494 * clipboard. Use with Transfer.isSupportedType. 495 * 496 * <p>The clipboards value is either one of the clipboard constants defined in 497 * class <code>DND</code>, or must be built by <em>bitwise OR</em>'ing together 498 * (that is, using the <code>int</code> "|" operator) two or more 499 * of those <code>DND</code> clipboard constants.</p> 500 * 501 * @param clipboards from which to get the data types 502 * @return array of data types currently available on the specified clipboard 503 * 504 * @exception SWTException <ul> 505 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 506 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 507 * </ul> 508 * 509 * @see Transfer#isSupportedType 510 * @see DND#CLIPBOARD 511 * @see DND#SELECTION_CLIPBOARD 512 * 513 * @since 3.1 514 */ 515 public TransferData[] getAvailableTypes(int clipboards) { 516 checkWidget(); 517 TransferData[] result = null; 518 if ((clipboards & DND.CLIPBOARD) !is 0) { 519 auto types = getAvailableClipboardTypes(); 520 result = new TransferData[types.length]; 521 for (int i = 0; i < types.length; i++) { 522 result[i] = new TransferData(); 523 result[i].type = types[i]; 524 } 525 } 526 if ((clipboards & DND.SELECTION_CLIPBOARD) !is 0) { 527 auto types = getAvailablePrimaryTypes(); 528 size_t offset = 0; 529 if (result !is null) { 530 TransferData[] newResult = new TransferData[result.length + types.length]; 531 System.arraycopy(result,0, newResult, 0, result.length); 532 offset = result.length; 533 result = newResult; 534 } else { 535 result = new TransferData[types.length]; 536 } 537 for (size_t i = 0; i < types.length; i++) { 538 result[offset+i] = new TransferData(); 539 result[offset+i].type = types[i]; 540 } 541 } 542 return result is null ? new TransferData[0] : result; 543 } 544 545 /** 546 * Returns a platform specific list of the data types currently available on the 547 * system clipboard. 548 * 549 * <p>Note: <code>getAvailableTypeNames</code> is a utility for writing a Transfer 550 * sub-class. It should NOT be used within an application because it provides 551 * platform specific information.</p> 552 * 553 * @return a platform specific list of the data types currently available on the 554 * system clipboard 555 * 556 * @exception SWTException <ul> 557 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 558 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 559 * </ul> 560 */ 561 public String[] getAvailableTypeNames() { 562 checkWidget(); 563 auto types1 = getAvailableClipboardTypes(); 564 auto types2 = getAvailablePrimaryTypes(); 565 String[] result = new String[types1.length + types2.length]; 566 int count = 0; 567 for (int i = 0; i < types1.length; i++) { 568 auto pName = OS.gdk_atom_name(types1[i]); 569 if (pName is null) { 570 continue; 571 } 572 String buffer = fromStringz( pName )._idup(); 573 OS.g_free (pName); 574 result[count++] = "GTKCLIPBOARD "~buffer; 575 } 576 for (int i = 0; i < types2.length; i++) { 577 auto pName = OS.gdk_atom_name(types2[i]); 578 if (pName is null) { 579 continue; 580 } 581 String buffer = fromStringz( pName )._idup(); 582 OS.g_free (pName); 583 result[count++] = "GTKPRIMARYCLIPBOARD "~buffer; 584 } 585 if (count < result.length){ 586 String[] temp = new String[count]; 587 System.arraycopy(result, 0, temp, 0, count); 588 result = temp; 589 } 590 return result; 591 } 592 593 private void*[] getAvailablePrimaryTypes() { 594 void*[] types; 595 auto selection_data = gtk_clipboard_wait_for_contents(GTKPRIMARYCLIPBOARD, TARGET); 596 if (selection_data !is null) { 597 try { 598 GtkSelectionData* gtkSelectionData = selection_data; 599 if (gtkSelectionData.length !is 0) { 600 types = cast(void*[])new int[gtkSelectionData.length * 8 / gtkSelectionData.format]; 601 OS.memmove( cast(void*)types.ptr, gtkSelectionData.data, gtkSelectionData.length ); 602 } 603 } finally { 604 OS.gtk_selection_data_free(selection_data); 605 } 606 } 607 return types; 608 } 609 private void*[] getAvailableClipboardTypes () { 610 void*[] types; 611 auto selection_data = gtk_clipboard_wait_for_contents(GTKCLIPBOARD, TARGET); 612 if (selection_data !is null) { 613 try { 614 GtkSelectionData* gtkSelectionData = selection_data; 615 if (gtkSelectionData.length !is 0) { 616 types = cast(void*[])new int[gtkSelectionData.length * 8 / gtkSelectionData.format]; 617 OS.memmove( cast(void*)types, gtkSelectionData.data, gtkSelectionData.length); 618 } 619 } finally { 620 OS.gtk_selection_data_free(selection_data); 621 } 622 } 623 return types; 624 } 625 626 GtkSelectionData* gtk_clipboard_wait_for_contents(void* clipboard, void* target) { 627 String key = "org.eclipse.swt.internal.gtk.dispatchEvent"; 628 Display display = this.display; 629 ArrayWrapperInt arr = new ArrayWrapperInt( [ OS.GDK_PROPERTY_NOTIFY, OS.GDK_SELECTION_CLEAR, OS.GDK_SELECTION_REQUEST, OS.GDK_SELECTION_NOTIFY ] ); 630 display.setData(key, arr ); 631 GtkSelectionData* selection_data = OS.gtk_clipboard_wait_for_contents(clipboard, target); 632 display.setData(key, null); 633 return selection_data; 634 } 635 }