diff --git a/src/main/java/org/jabref/Globals.java b/src/main/java/org/jabref/Globals.java
index 71466ee47c7..12531280708 100644
--- a/src/main/java/org/jabref/Globals.java
+++ b/src/main/java/org/jabref/Globals.java
@@ -56,13 +56,11 @@ public class Globals {
/**
* Manager for the state of the GUI.
*/
-
- public static ClipBoardManager clipboardManager = new ClipBoardManager();
-
public static StateManager stateManager = new StateManager();
public static ExporterFactory exportFactory;
public static CountingUndoManager undoManager = new CountingUndoManager();
public static BibEntryTypesManager entryTypesManager = new BibEntryTypesManager();
+ public static ClipBoardManager clipboardManager = new ClipBoardManager();
// Key binding preferences
private static KeyBindingRepository keyBindingRepository;
private static DefaultFileUpdateMonitor fileUpdateMonitor;
diff --git a/src/main/java/org/jabref/gui/ClipBoardManager.java b/src/main/java/org/jabref/gui/ClipBoardManager.java
index 0411f8afd4e..64bc6617533 100644
--- a/src/main/java/org/jabref/gui/ClipBoardManager.java
+++ b/src/main/java/org/jabref/gui/ClipBoardManager.java
@@ -1,5 +1,10 @@
package org.jabref.gui;
+import java.awt.Toolkit;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@@ -7,9 +12,11 @@
import java.util.List;
import java.util.Optional;
+import javafx.scene.control.TextInputControl;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DataFormat;
+import javafx.scene.input.MouseButton;
import org.jabref.Globals;
import org.jabref.logic.bibtex.BibEntryWriter;
@@ -30,36 +37,53 @@
import org.slf4j.LoggerFactory;
public class ClipBoardManager {
+
public static final DataFormat XML = new DataFormat("application/xml");
private static final Logger LOGGER = LoggerFactory.getLogger(ClipBoardManager.class);
- private final Clipboard clipboard;
- private final ImportFormatReader importFormatReader;
+ private static Clipboard clipboard;
+ private static java.awt.datatransfer.Clipboard primary;
+ private static ImportFormatReader importFormatReader;
- public ClipBoardManager() {
- this(Clipboard.getSystemClipboard(), Globals.IMPORT_FORMAT_READER);
+ public ClipBoardManager(Clipboard clipboard, java.awt.datatransfer.Clipboard primary, ImportFormatReader importFormatReader) {
+ ClipBoardManager.clipboard = clipboard;
+ ClipBoardManager.primary = primary;
+ ClipBoardManager.importFormatReader = importFormatReader;
}
- public ClipBoardManager(Clipboard clipboard, ImportFormatReader importFormatReader) {
- this.clipboard = clipboard;
- this.importFormatReader = importFormatReader;
+ public ClipBoardManager() {
+ this(Clipboard.getSystemClipboard(), Toolkit.getDefaultToolkit().getSystemSelection(), Globals.IMPORT_FORMAT_READER);
}
/**
- * Puts content onto the clipboard.
+ * Add X11 clipboard support to a text input control.
+ * It is necessary to call this method in every input where you want to use it:
+ * {@code ClipBoardManager.addX11Support(TextInputControl input);}.
+ *
+ * @param input the TextInputControl (e.g., TextField, TextArea, and children) where adding this functionality.
+ * @see Short summary for X11 clipboards
+ * @see Longer text over clipboards
*/
- public void setContent(ClipboardContent content) {
- clipboard.setContent(content);
+ public static void addX11Support(TextInputControl input) {
+ input.selectedTextProperty().addListener((observable, oldValue, newValue) -> {
+ if (!newValue.isEmpty()) {
+ primary.setContents(new StringSelection(newValue), null);
+ }
+ });
+ input.setOnMouseClicked(event -> {
+ if (event.getButton() == MouseButton.MIDDLE) {
+ input.insertText(input.getCaretPosition(), getContentsPrimary());
+ }
+ });
}
/**
- * Get the String residing on the clipboard.
+ * Get the String residing on the system clipboard.
*
- * @return any text found on the Clipboard; if none found, return an
- * empty String.
+ * @return any text found on the Clipboard; if none found, return an empty String.
*/
- public String getContents() {
+ public static String getContents() {
String result = clipboard.getString();
if (result == null) {
return "";
@@ -67,16 +91,54 @@ public String getContents() {
return result;
}
+ /**
+ * Get the String residing on the primary clipboard.
+ *
+ * @return any text found on the primary Clipboard; if none found, try with the system clipboard.
+ */
+ public static String getContentsPrimary() {
+ Transferable contents = primary.getContents(null);
+ if (contents != null && contents.isDataFlavorSupported(DataFlavor.stringFlavor)) {
+ try {
+ return (String) contents.getTransferData(DataFlavor.stringFlavor);
+ } catch (UnsupportedFlavorException | IOException e) {
+ LOGGER.warn(e.getMessage());
+ }
+ }
+ return getContents();
+ }
+
+ /**
+ * Puts content onto the system clipboard.
+ *
+ * @param content the ClipboardContent to set as current value of the system clipboard.
+ */
+ public void setContent(ClipboardContent content) {
+ clipboard.setContent(content);
+ setPrimaryClipboardContent(content);
+ }
+
+ /**
+ * Puts content onto the primary clipboard.
+ *
+ * @param content the ClipboardContent to set as current value of the primary clipboard.
+ */
+ public void setPrimaryClipboardContent(ClipboardContent content) {
+ primary.setContents(new StringSelection(content.getString()), null);
+ }
+
public void setHtmlContent(String html) {
final ClipboardContent content = new ClipboardContent();
content.putHtml(html);
clipboard.setContent(content);
+ setPrimaryClipboardContent(content);
}
public void setContent(String string) {
final ClipboardContent content = new ClipboardContent();
content.putString(string);
clipboard.setContent(content);
+ setPrimaryClipboardContent(content);
}
public void setContent(List entries) throws IOException {
@@ -86,6 +148,7 @@ public void setContent(List entries) throws IOException {
content.put(DragAndDropDataFormats.ENTRIES, serializedEntries);
content.putString(serializedEntries);
clipboard.setContent(content);
+ setPrimaryClipboardContent(content);
}
public List extractData() {
diff --git a/src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java b/src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java
index 65a55854974..13a7f7f6ac3 100644
--- a/src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java
+++ b/src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java
@@ -10,6 +10,8 @@
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
+import org.jabref.gui.ClipBoardManager;
+
public class EditorTextArea extends javafx.scene.control.TextArea implements Initializable, ContextMenuAddable {
private final ContextMenu contextMenu = new ContextMenu();
@@ -29,6 +31,8 @@ public EditorTextArea(final String text) {
// Hide horizontal scrollbar and always wrap text
setWrapText(true);
+
+ ClipBoardManager.addX11Support(this);
}
@Override
diff --git a/src/main/java/org/jabref/gui/fieldeditors/EditorTextField.java b/src/main/java/org/jabref/gui/fieldeditors/EditorTextField.java
index a10583e2774..215083980a8 100644
--- a/src/main/java/org/jabref/gui/fieldeditors/EditorTextField.java
+++ b/src/main/java/org/jabref/gui/fieldeditors/EditorTextField.java
@@ -11,6 +11,8 @@
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
+import org.jabref.gui.ClipBoardManager;
+
public class EditorTextField extends javafx.scene.control.TextField implements Initializable, ContextMenuAddable {
private final ContextMenu contextMenu = new ContextMenu();
@@ -25,6 +27,8 @@ public EditorTextField(final String text) {
// Always fill out all the available space
setPrefHeight(Double.POSITIVE_INFINITY);
HBox.setHgrow(this, Priority.ALWAYS);
+
+ ClipBoardManager.addX11Support(this);
}
@Override
diff --git a/src/main/java/org/jabref/gui/search/GlobalSearchBar.java b/src/main/java/org/jabref/gui/search/GlobalSearchBar.java
index 6938411b4ad..9ce56f914b7 100644
--- a/src/main/java/org/jabref/gui/search/GlobalSearchBar.java
+++ b/src/main/java/org/jabref/gui/search/GlobalSearchBar.java
@@ -34,6 +34,7 @@
import org.jabref.Globals;
import org.jabref.gui.BasePanel;
+import org.jabref.gui.ClipBoardManager;
import org.jabref.gui.JabRefFrame;
import org.jabref.gui.StateManager;
import org.jabref.gui.autocompleter.AppendPersonNamesStrategy;
@@ -111,6 +112,8 @@ public GlobalSearchBar(JabRefFrame frame, StateManager stateManager) {
}
});
+ ClipBoardManager.addX11Support(searchField);
+
regularExp = IconTheme.JabRefIcons.REG_EX.asToggleButton();
regularExp.setSelected(searchPreferences.isRegularExpression());
regularExp.setTooltip(new Tooltip(Localization.lang("regular expression")));