我正在开发LibGDX游戏,游戏中有登录界面和注册界面。 HTML版本的游戏具有剪贴板的沙箱环境,意味着:
从游戏中复制的任何东西都不能粘贴在游戏外面。 从外面复制的任何内容都不能粘贴在游戏的文本区域中
我只是想复制文本,有什么办法可以将沙箱剪贴板与系统剪贴板合并吗?
我想要的是: 当用户在文本字段中执行Ctr + V时,它应该从textfield&中的系统剪贴板中获取文本。当用户按Ctr + C时:它应该将文本放在系统剪贴板中
我正在尝试:
public class HtmlLauncher extends GwtApplication {
private static HtmlLauncher instance;
public void onModuleLoad() {
instance = this;
setLoadingListener(new LoadingListener() {
@Override
public void beforeSetup() {}
@Override
public void afterSetup() {
setupCopyListener();
}
});
}
native void setupCopyListener()
/*-{
var htmlLauncher_onCopy = $entry(@com.myapp.game.client.HtmlLauncher::addToClipboard());
$wnd.addEventListener("copy", htmlLauncher_onCopy, false);
}-*/
;
public static void addToClipboard() {
instance.copy();
}
private void copy() {
//getClipboard().setContents("");
consoleLog("copied");
}
}
任何人都可以帮助我:
编辑(5月2日,尝试了JustACluelessNewbie的建议): 继承剪贴板:
public class MyClipboard implements com.badlogic.gdx.utils.Clipboard{
private String cachedContent = "";
public MyClipboard() {
createTextArea();
}
@Override
public String getContents() {
String contents = getClipBoard();
return (contents == null) ? cachedContent : cachedContent = contents;
}
@Override
public void setContents(String content) {
cachedContent = content == null ? "" : content;
setClipBoard(content);
}
public static native void createTextArea() /*-{
var textArea = document.createElement('textarea');
textArea.style.position='fixed';
textArea.style.top=0;
textArea.style.left=0;
textArea.style.width='2em';
textArea.style.height='2em';
textArea.style.padding=0;
textArea.style.border='none';
textArea.style.outline='none';
textArea.style.boxShadow='none';
textArea.style.background='transparent';
$wnd._copy=textArea;
}-*/;
public static native String getClipBoard() /*-{
if(window.clipboardData){
return window.clipboardData.getData('Text');
}else {
document.body.appendChild($wnd._copy);
try{
$wnd._copy.value = "";
$wnd._copy.focus();
$wnd._copy.select();
console.log(document.queryCommandSupported("paste")); //prints true
var result = document.execCommand('paste');
console.log(result); //prints false
return $wnd._copy.value;
}catch(err){
return null;
}finally{
document.body.removeChild($wnd._copy);
}
}
}-*/;
public static native void setClipBoard(String content) /*-{
document.body.appendChild($wnd._copy);
try{
$wnd._copy.value = content;
$wnd._copy.select();
var result = document.execCommand('copy');
console.log("after exec copy "+result)
}catch(err){
console.log("error:"+err);
}finally{
document.body.removeChild($wnd._copy);
}
}-*/ ;
}
答案 0 :(得分:1)
你是对的 - GWT剪贴板甚至不尝试访问“全局”剪贴板,仅在应用程序本身内复制和粘贴数据。您可以尝试将GwtClipboard
替换为使用本机代码访问剪贴板数据的实现。您可以尝试转换Clipboard
实施实验,未完成Dragome backend:您可以找到它here。它基本上是这样的:
public class DragomeClipboard implements Clipboard {
private String cachedContent = "";
public DragomeClipboard () {
ScriptHelper.evalNoResult(
"var textArea=document.createElement('textarea');textArea.style.position='fixed';textArea.style.top=0;textArea.style.left=0;textArea.style.width='2em';textArea.style.height='2em';textArea.style.padding=0;textArea.style.border='none';textArea.style.outline='none';textArea.style.boxShadow='none';textArea.style.background='transparent';this._copy=textArea;",
this);
}
@Override
public String getContents () {
try {
ScriptHelper.put("_cache", cachedContent, this);
final String content = String.valueOf(ScriptHelper.eval(
"if(window.clipboardData){return window.clipboardData.getData('Text');}else{document.body.appendChild(this._copy);try{this._copy.select();document.execCommand('paste');return this._copy.value;}catch(err){return _cache;}finally{document.body.removeChild(this._copy;}}",
this));
cachedContent = content;
return content;
} catch (final Throwable exception) {
Exceptions.ignore(exception);
return cachedContent;
}
}
@Override
public void setContents (final String content) {
cachedContent = content == null ? "" : content;
ScriptHelper.evalNoResult(
"document.body.appendChild(this._copy);try{this._copy.select();document.execCommand('copy');}catch(err){}finally{document.body.removeChild(this._copy);}",
this);
}
}
我认为这是未经测试的,但绝对值得一试。请记住,大多数浏览器都会禁止访问剪贴板,除非它是由用户输入事件进行的;由于复制很可能是不直接由本机事件侦听器处理(事件被轮询并稍后处理),因此它可能无法正常工作。
您可以覆盖GwtApplication#getClipboard()
并返回已转换的实现 - 如果这样做,它应该被所有LibGDX实用程序使用,例如Scene2D小部件。
答案 1 :(得分:0)
最后,我得到了它的工作,如果有人还在寻找这个
,我会发布我的答案package myPackage;
public class HtmlLauncher extends GwtApplication {
private static HtmlLauncher instance;
@Override
public void onModuleLoad() {
super.onModuleLoad();
instance = this;
setLoadingListener(new LoadingListener() {
@Override
public void beforeSetup() {
}
@Override
public void afterSetup() {
setupCopyListener();
}
});
}
native void setupCopyListener() /*-{
var self = this;
var isSafari = navigator.appVersion.search('Safari') != -1 && navigator.appVersion.search('Chrome') == -1 && navigator.appVersion.search('CrMo') == -1 && navigator.appVersion.search('CriOS') == -1;
var isIe = (navigator.userAgent.toLowerCase().indexOf("msie") != -1 || navigator.userAgent.toLowerCase().indexOf("trident") != -1);
var ieClipboardDiv = $doc.getElementById('#ie-clipboard-contenteditable');
var hiddenInput = $doc.getElementById("hidden-input");
var getTextToCopy = $entry(function(){
return self.@myPackage.HtmlLauncher::copy()();
});
var pasteText = $entry(function(text){
self.@myPackage.HtmlLauncher::paste(Ljava/lang/String;)(text);
});
var focusHiddenArea = function() {
// In order to ensure that the browser will fire clipboard events, we always need to have something selected
hiddenInput.value = '';
hiddenInput.focus();
hiddenInput.select();
};
// Focuses an element to be ready for copy/paste (used exclusively for IE)
var focusIeClipboardDiv = function() {
ieClipboardDiv.focus();
var range = document.createRange();
range.selectNodeContents((ieClipboardDiv.get(0)));
var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
};
// For IE, we can get/set Text or URL just as we normally would,
// but to get HTML, we need to let the browser perform the copy or paste
// in a contenteditable div.
var ieClipboardEvent = function(clipboardEvent) {
var clipboardData = window.clipboardData;
if (clipboardEvent == 'cut' || clipboardEvent == 'copy') {
clipboardData.setData('Text', getTextToCopy());
focusIeClipboardDiv();
setTimeout(function() {
focusHiddenArea();
ieClipboardDiv.empty();
}, 0);
}
if (clipboardEvent == 'paste') {
var clipboardText = clipboardData.getData('Text');
ieClipboardDiv.empty();
setTimeout(function() {
pasteText(clipboardText);
ieClipboardDiv.empty();
focusHiddenArea();
}, 0);
}
};
// For every broswer except IE, we can easily get and set data on the clipboard
var standardClipboardEvent = function(clipboardEvent, event) {
var clipboardData = event.clipboardData;
if (clipboardEvent == 'cut' || clipboardEvent == 'copy') {
clipboardData.setData('text/plain', getTextToCopy());
}
if (clipboardEvent == 'paste') {
pasteText(clipboardData.getData('text/plain'));
}
};
['cut', 'copy', 'paste'].forEach(function (event) {
$doc.addEventListener(event,function (e) {
console.log(event);
if(isIe) {
ieClipboardEvent(event);
} else {
standardClipboardEvent(event, e);
focusHiddenArea();
e.preventDefault();
}
})
})
}-*/;
private void paste(String text) {
consoleLog("in paste"+text);
String oldText = getClipboard().getContents();
if(!oldText.equals(text)){
getClipboard().setContents(text);
Actor focusedActor = ((BasicScreen)((Game)getApplicationListener()).getScreen()).getStage().getKeyboardFocus();
if (focusedActor != null && focusedActor instanceof TextField) {
if(!oldText.equals("")) {
String textFieldText = ((TextField)focusedActor).getText();
textFieldText = textFieldText.substring(0,textFieldText.lastIndexOf(oldText));
((TextField)focusedActor).setText(textFieldText);
}
((TextField)focusedActor).appendText(text);
}
}
}
private String copy() {
return getClipboard().getContents();
}
}
我为所有屏幕创建了一个超类,这个问题需要的最小结构:
public abstract class BasicScreen extends ScreenAdapter implements InputProcessor {
protected MyStage stage;
public BasicScreen () {
stage = new MyStage();
}
public MyStage getStage () {
return stage;
}
}
您需要在同一阶段添加文本字段
在index.html中,在内部添加以下两行:<div id="ie-clipboard-contenteditable" class="hidden" contenteditable="true"></div>
<input id="hidden-input" class="hidden" type="text" value=""/>
在css中,添加:
.hidden {
position: fixed;
bottom: 0;
left: 0;
width: 10px;
height: 10px;
display: block;
font-size: 1;
z-index: -1;
color: transparent;
background: transparent;
overflow: hidden;
border: none;
padding: 0;
resize: none;
outline: none;
-webkit-user-select: text;
user-select: text;
/* Because for user-select:none, Safari won't allow input */
}
它在chrome中运行得很好,没有在其他浏览器上测试过。
我参考了: https://www.lucidchart.com/techblog/2014/12/02/definitive-guide-copying-pasting-javascript/