Skip to content

Commit

Permalink
Make clipboard support use AWT instead of JavaFX
Browse files Browse the repository at this point in the history
Fixes the Telegram bugs for me. Let's see if it fixes defnax' issues.
  • Loading branch information
zapek committed Nov 20, 2024
1 parent 5426cf8 commit 78c1e6c
Show file tree
Hide file tree
Showing 12 changed files with 108 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import io.xeres.ui.custom.ReadOnlyTextField;
import io.xeres.ui.custom.led.LedControl;
import io.xeres.ui.custom.led.LedStatus;
import io.xeres.ui.support.clipboard.ClipboardUtils;
import io.xeres.ui.support.tray.TrayService;
import io.xeres.ui.support.uri.*;
import io.xeres.ui.support.util.TooltipUtils;
Expand All @@ -50,8 +51,6 @@
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.image.ImageView;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
Expand Down Expand Up @@ -349,12 +348,7 @@ public void onHidden()
private void copyOwnId()
{
var rsIdResponse = locationClient.getRSId(OWN_LOCATION_ID, Type.ANY);
rsIdResponse.subscribe(reply -> Platform.runLater(() -> {
var clipboard = Clipboard.getSystemClipboard();
var content = new ClipboardContent();
content.putString(reply.rsId());
clipboard.setContent(content);
}));
rsIdResponse.subscribe(reply -> Platform.runLater(() -> ClipboardUtils.copyTextToClipboard(reply.rsId())));
}

private void showQrCode()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import io.xeres.ui.custom.asyncimage.ImageCache;
import io.xeres.ui.support.chat.ChatCommand;
import io.xeres.ui.support.chat.NicknameCompleter;
import io.xeres.ui.support.clipboard.ClipboardUtils;
import io.xeres.ui.support.contextmenu.XContextMenu;
import io.xeres.ui.support.markdown.MarkdownService;
import io.xeres.ui.support.preference.PreferenceService;
Expand All @@ -52,7 +53,10 @@
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.image.ImageView;
import javafx.scene.input.*;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
Expand Down Expand Up @@ -313,10 +317,8 @@ private void createRoomTreeContextMenu()
copyLinkItem.setId(COPY_LINK_MENU_ID);
copyLinkItem.setGraphic(new FontIcon(MaterialDesignL.LINK_VARIANT));
copyLinkItem.setOnAction(event -> {
var clipboardContent = new ClipboardContent();
var chatRoomInfo = ((RoomHolder) event.getSource()).getRoomInfo();
clipboardContent.putString(ChatRoomUriFactory.generate(chatRoomInfo.getName(), chatRoomInfo.getId()));
Clipboard.getSystemClipboard().setContent(clipboardContent);
ClipboardUtils.copyTextToClipboard(ChatRoomUriFactory.generate(chatRoomInfo.getName(), chatRoomInfo.getId()));
});

var xContextMenu = new XContextMenu<RoomHolder>(subscribeItem, unsubscribeItem, new SeparatorMenuItem(), copyLinkItem);
Expand Down Expand Up @@ -656,7 +658,7 @@ private void handleInputKeys(KeyEvent event)

if (PASTE_KEY.match(event))
{
var image = Clipboard.getSystemClipboard().getImage();
var image = ClipboardUtils.getImageFromClipboard();
if (image != null)
{
imagePreview.setImage(image);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,13 @@
package io.xeres.ui.controller.debug;

import io.xeres.ui.controller.WindowController;
import io.xeres.ui.support.clipboard.ClipboardUtils;
import io.xeres.ui.support.contextmenu.XContextMenu;
import javafx.beans.property.SimpleStringProperty;
import javafx.fxml.FXML;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import net.rgielen.fxweaver.core.FxmlView;
import org.springframework.stereotype.Component;

Expand Down Expand Up @@ -69,11 +68,9 @@ public void initialize()
tableName.setSortType(ASCENDING);

copyAll.setOnAction(event -> {
var clipboardContent = new ClipboardContent();
var sb = new StringBuilder();
getSortedProperties().forEach((k, v) -> sb.append(k).append(": ").append(showLineSeparator(v)).append("\n"));
clipboardContent.putString(showLineSeparator(sb.toString()));
Clipboard.getSystemClipboard().setContent(clipboardContent);
ClipboardUtils.copyTextToClipboard(showLineSeparator(sb.toString()));
});
}

Expand Down Expand Up @@ -104,9 +101,7 @@ private void createPropertiesTableViewContextMenu()
@SuppressWarnings("unchecked") var entry = (Map.Entry<String, String>) event.getSource();
if (entry != null)
{
var clipboardContent = new ClipboardContent();
clipboardContent.putString(entry.getKey() + " = " + showLineSeparator(entry.getValue()));
Clipboard.getSystemClipboard().setContent(clipboardContent);
ClipboardUtils.copyTextToClipboard(entry.getKey() + " = " + showLineSeparator(entry.getValue()));
}
});
var xContextMenu = new XContextMenu<Map.Entry<String, String>>(copyItem);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import io.xeres.common.i18n.I18nUtils;
import io.xeres.common.id.Sha1Sum;
import io.xeres.ui.client.FileClient;
import io.xeres.ui.support.clipboard.ClipboardUtils;
import io.xeres.ui.support.contextmenu.XContextMenu;
import io.xeres.ui.support.uri.FileUriFactory;
import javafx.application.Platform;
Expand All @@ -34,8 +35,6 @@
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.layout.StackPane;
import org.kordamp.ikonli.javafx.FontIcon;
import org.kordamp.ikonli.materialdesign2.MaterialDesignF;
Expand Down Expand Up @@ -174,9 +173,7 @@ private void createFilesTableViewContextMenu()
copyLinkItem.setOnAction(event -> {
if (event.getSource() instanceof FileResult file)
{
var clipboardContent = new ClipboardContent();
clipboardContent.putString(FileUriFactory.generate(file.name(), file.size(), Sha1Sum.fromString(file.hash())));
Clipboard.getSystemClipboard().setContent(clipboardContent);
ClipboardUtils.copyTextToClipboard(FileUriFactory.generate(file.name(), file.size(), Sha1Sum.fromString(file.hash())));
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import io.xeres.ui.client.NotificationClient;
import io.xeres.ui.controller.Controller;
import io.xeres.ui.controller.TabActivation;
import io.xeres.ui.support.clipboard.ClipboardUtils;
import io.xeres.ui.support.contextmenu.XContextMenu;
import io.xeres.ui.support.uri.SearchUri;
import io.xeres.ui.support.uri.SearchUriFactory;
Expand All @@ -35,8 +36,6 @@
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextField;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.KeyCode;
import net.rgielen.fxweaver.core.FxmlView;
import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -158,10 +157,8 @@ private void createContextMenu()
copyLinkItem.setId(COPY_LINK_MENU_ID);
copyLinkItem.setGraphic(new FontIcon(MaterialDesignL.LINK_VARIANT));
copyLinkItem.setOnAction(event -> {
var clipboardContent = new ClipboardContent();
var fileResultView = (FileResultView) event.getSource();
clipboardContent.putString(SearchUriFactory.generate(StringUtils.left(fileResultView.getText(), 50), fileResultView.getText()));
Clipboard.getSystemClipboard().setContent(clipboardContent);
ClipboardUtils.copyTextToClipboard(SearchUriFactory.generate(StringUtils.left(fileResultView.getText(), 50), fileResultView.getText()));
});

var xContextMenu = new XContextMenu<Tab>(copyLinkItem);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import io.xeres.ui.custom.ProgressPane;
import io.xeres.ui.custom.asyncimage.ImageCache;
import io.xeres.ui.model.forum.ForumMapper;
import io.xeres.ui.support.clipboard.ClipboardUtils;
import io.xeres.ui.support.contentline.Content;
import io.xeres.ui.support.contextmenu.XContextMenu;
import io.xeres.ui.support.markdown.MarkdownService;
Expand All @@ -52,8 +53,6 @@
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.control.cell.TreeItemPropertyValueFactory;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.layout.GridPane;
import javafx.scene.text.TextFlow;
import net.rgielen.fxweaver.core.FxmlView;
Expand Down Expand Up @@ -320,10 +319,8 @@ private void createForumTreeContextMenu()
copyLinkItem.setId(COPY_LINK_MENU_ID);
copyLinkItem.setGraphic(new FontIcon(MaterialDesignL.LINK_VARIANT));
copyLinkItem.setOnAction(event -> {
var clipboardContent = new ClipboardContent();
var forumGroup = ((ForumGroup) event.getSource());
clipboardContent.putString(ForumUriFactory.generate(forumGroup.getName(), forumGroup.getGxsId()));
Clipboard.getSystemClipboard().setContent(clipboardContent);
ClipboardUtils.copyTextToClipboard(ForumUriFactory.generate(forumGroup.getName(), forumGroup.getGxsId()));
});

var xContextMenu = new XContextMenu<ForumGroup>(subscribeItem, unsubscribeItem, new SeparatorMenuItem(), copyLinkItem);
Expand Down Expand Up @@ -351,10 +348,8 @@ private void createForumMessageTableViewContextMenu()
copyLinkItem.setId(COPY_LINK_MENU_ID);
copyLinkItem.setGraphic(new FontIcon(MaterialDesignL.LINK_VARIANT));
copyLinkItem.setOnAction(event -> {
var clipboardContent = new ClipboardContent();
@SuppressWarnings("unchecked") var forumMessage = ((TreeItem<ForumMessage>) event.getSource()).getValue();
clipboardContent.putString(ForumUriFactory.generate(forumMessage.getName(), forumMessage.getGxsId(), forumMessage.getMessageId()));
Clipboard.getSystemClipboard().setContent(clipboardContent);
ClipboardUtils.copyTextToClipboard(ForumUriFactory.generate(forumMessage.getName(), forumMessage.getGxsId(), forumMessage.getMessageId()));
});

var xContextMenu = new XContextMenu<ForumMessage>(replyItem, new SeparatorMenuItem(), copyLinkItem);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import io.xeres.ui.custom.asyncimage.ImageCache;
import io.xeres.ui.model.profile.Profile;
import io.xeres.ui.support.chat.ChatCommand;
import io.xeres.ui.support.clipboard.ClipboardUtils;
import io.xeres.ui.support.markdown.MarkdownService;
import io.xeres.ui.support.uri.FileUri;
import io.xeres.ui.support.uri.FileUriFactory;
Expand Down Expand Up @@ -382,7 +383,7 @@ private void handleInputKeys(KeyEvent event)
{
if (PASTE_KEY.match(event))
{
var image = Clipboard.getSystemClipboard().getImage();
var image = ClipboardUtils.getImageFromClipboard();
if (image != null)
{
sendImageViewToMessage(new ImageView(image));
Expand Down
8 changes: 6 additions & 2 deletions ui/src/main/java/io/xeres/ui/custom/EditorView.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import io.xeres.common.i18n.I18nUtils;
import io.xeres.ui.client.LocationClient;
import io.xeres.ui.support.clipboard.ClipboardUtils;
import io.xeres.ui.support.contentline.Content;
import io.xeres.ui.support.markdown.MarkdownService;
import io.xeres.ui.support.util.ImageUtils;
Expand All @@ -31,7 +32,10 @@
import javafx.fxml.FXMLLoader;
import javafx.scene.control.*;
import javafx.scene.image.ImageView;
import javafx.scene.input.*;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.VBox;
import javafx.scene.text.TextFlow;
import javafx.stage.Window;
Expand Down Expand Up @@ -392,7 +396,7 @@ private void handleInputKeys(KeyEvent event)

if (PASTE_KEY.match(event))
{
var image = Clipboard.getSystemClipboard().getImage();
var image = ClipboardUtils.getImageFromClipboard();
if (image != null)
{
var imageView = new ImageView(image);
Expand Down
75 changes: 75 additions & 0 deletions ui/src/main/java/io/xeres/ui/support/clipboard/ClipboardUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2024 by David Gerber - https://zapek.com
*
* This file is part of Xeres.
*
* Xeres is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Xeres is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Xeres. If not, see <http://www.gnu.org/licenses/>.
*/

package io.xeres.ui.support.clipboard;

import javafx.embed.swing.SwingFXUtils;
import javafx.scene.image.Image;

import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.image.BufferedImage;
import java.io.IOException;

/**
* Utility class to use the clipboard. This implementation uses AWT because the clipboard support of JavaFX is, quite frankly, a
* royal piece of shit.
* <p>
* Fails to work with some bitmaps (for example from Telegram, Windows 10 and print screen, Chrome, ...).
* <p>
* Fails with data URIs because it tries to find out if the image is a supported format and even though it is, the URL is "wrong" for it.
*/
public final class ClipboardUtils
{
private ClipboardUtils()
{
throw new UnsupportedOperationException("Utility class");
}

public static Image getImageFromClipboard()
{
var transferable = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
if (transferable != null && transferable.isDataFlavorSupported(DataFlavor.imageFlavor))
{
BufferedImage image;
try
{
image = (BufferedImage) transferable.getTransferData(DataFlavor.imageFlavor);
}
catch (UnsupportedFlavorException | IOException e)
{
throw new RuntimeException(e);
}
return SwingFXUtils.toFXImage(image, null);
}
return null;
}

public static void copyImageToClipboard(Image image)
{
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new ImageSelection(SwingFXUtils.fromFXImage(image, null)), null);
}

public static void copyTextToClipboard(String text)
{
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(text), null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* along with Xeres. If not, see <http://www.gnu.org/licenses/>.
*/

package io.xeres.ui.support.util;
package io.xeres.ui.support.clipboard;

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
Expand All @@ -27,7 +27,7 @@
/**
* This class is needed to save images to the clipboard using AWT.
*/
public class ImageSelection implements Transferable
class ImageSelection implements Transferable
{
private final BufferedImage image;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

import io.xeres.common.i18n.I18nUtils;
import io.xeres.ui.custom.ResizeableImageView;
import io.xeres.ui.support.util.ImageSelection;
import io.xeres.ui.support.clipboard.ClipboardUtils;
import io.xeres.ui.support.util.UiUtils;
import javafx.embed.swing.SwingFXUtils;
import javafx.event.ActionEvent;
Expand All @@ -47,7 +47,6 @@
import org.kordamp.ikonli.materialdesign2.MaterialDesignI;

import javax.imageio.ImageIO;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.time.Instant;
Expand Down Expand Up @@ -104,12 +103,7 @@ public Node getNode()

private static void copyToClipboard(ActionEvent event)
{
// We cannot use ClipboardContent/putImage() here because
// JavaFX tries to find out if the image url is a supported format
// and this fails with data: URLs. It would have worked with a null
// URL, but one would have to copy the Image from a ByteBufferArray which
// is more complicated than just using AWT, which gets it right (sigh).
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new ImageSelection(SwingFXUtils.fromFXImage(getImageViewFromEvent(event).getImage(), null)), null);
ClipboardUtils.copyImageToClipboard(getImageViewFromEvent(event).getImage());
}

private static void saveAs(ActionEvent event)
Expand Down
Loading

0 comments on commit 78c1e6c

Please sign in to comment.