-
-
Notifications
You must be signed in to change notification settings - Fork 11k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bring back old Copy / Paste system #1771
Comments
The content pasted by with Alt+v should be the same as the one pasted with Alt+Shift+v (and the same as the one pasted with Ctrl+v). If this is not the case, then probably Which Android version, which Android ROM? Could you try with another device? |
I've got an Samsung Galaxy S9+ and Android 10 samsung rom. But, why did you change |
To forward the Ctrl key to the device. See v1.15 highlights and #1598 for more details. |
When i hit |
Oh, wait, do you use v1.16? Because there was a bug in v1.15: #1658 |
Yes, i use the v1.16 version |
OK, so IIUC, the second time you press Ctrl+v, it correctly pastes the expected content, right? |
Here's a video example : https://streamable.com/r1k9nc |
OK, thank you for the video. 👍 So it seems that You could also test I think it's the very same issue as #1750. I would say this is a device bug: once the content is in the clipboard (as shown above the device keyboard), injecting Could you capture the logcat content when you press Ctrl+v in the scrcpy window for the first time (with a new random content, different from the previous one), please? Start scrcpy and from a new terminal, execute: adb logcat -c # clear
# copy some text and press Ctrl+v in the scrcpy window
adb logcat -d > logcat.txt |
When i do |
Maybe it's a bug with Google Keyboard (the content is well copied in the clipboard of GBoard), but before the v1.16, things work perfectly with the "letter by letter paste" ( |
OK, so it suggests a device system bug (or intended restriction). The method scrcpy uses to set the clipboard is "public" (usable by any app): I'm interested to know if you set the text from some app using this API and try to paste with There are probably some simple "clipboard manager" apps which allow to explicitly set some text to the clipboard using this. |
I test with https://play.google.com/store/apps/details?id=devdnua.clipboard and it work when i paste the clipboard content |
😕 |
I wrote a minimal scrcpy-like sample application to get and set the clipboard. Download Then push it to the device: adb push clipboard.dex /data/local/tmp/ Then, you can execute: # get the current clipboard text
adb shell CLASSPATH=/data/local/tmp/clipboard.dex app_process / Clipboard get
# set the clipboard text
adb shell CLASSPATH=/data/local/tmp/clipboard.dex app_process / Clipboard set abcdefgh Please try to set the clipboard, check the result by reading the current content. What is the behavior? source codeimport android.content.ClipData;
import android.os.Build;
import android.os.IBinder;
import android.os.IInterface;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Clipboard {
private static final String PACKAGE_NAME = "com.android.shell";
private static final int USER_ID = 0;
private static Method getPrimaryClipMethod;
private static Method setPrimaryClipMethod;
private static boolean legacySet;
private static IInterface getService(String service, String type) {
try {
Method getServiceMethod = Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", String.class);
IBinder binder = (IBinder) getServiceMethod.invoke(null, service);
Method asInterfaceMethod = Class.forName(type + "$Stub").getMethod("asInterface", IBinder.class);
return (IInterface) asInterfaceMethod.invoke(null, binder);
} catch (Exception e) {
throw new AssertionError(e);
}
}
private static IInterface getClipboardManager() {
return getService("clipboard", "android.content.IClipboard");
}
private static Method getGetPrimaryClipMethod(IInterface manager) throws NoSuchMethodException {
if (getPrimaryClipMethod == null) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class);
} else {
getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, int.class);
}
}
return getPrimaryClipMethod;
}
private static Method getSetPrimaryClipMethod(IInterface manager) throws NoSuchMethodException {
if (setPrimaryClipMethod == null) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class);
} else {
setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class, int.class);
}
}
return setPrimaryClipMethod;
}
private static ClipData getPrimaryClip(Method method, IInterface manager) throws InvocationTargetException, IllegalAccessException {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
return (ClipData) method.invoke(manager, PACKAGE_NAME);
}
return (ClipData) method.invoke(manager, PACKAGE_NAME, USER_ID);
}
private static void setPrimaryClip(Method method, IInterface manager, ClipData clipData)
throws InvocationTargetException, IllegalAccessException {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
method.invoke(manager, clipData, PACKAGE_NAME);
} else {
method.invoke(manager, clipData, PACKAGE_NAME, USER_ID);
}
}
public static CharSequence getText(IInterface manager) {
try {
Method method = getGetPrimaryClipMethod(manager);
ClipData clipData = getPrimaryClip(method, manager);
if (clipData == null || clipData.getItemCount() == 0) {
return null;
}
return clipData.getItemAt(0).getText();
} catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
System.err.println("Could not invoke method");
return null;
}
}
public static boolean setText(IInterface manager, CharSequence text) {
try {
Method method = getSetPrimaryClipMethod(manager);
ClipData clipData = ClipData.newPlainText(null, text);
setPrimaryClip(method, manager, clipData);
return true;
} catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
System.err.println("Could not invoke method");
return false;
}
}
private static void syntax() {
System.err.println("Syntax: adb shell CLASSPATH=/data/local/tmp/clipboard app_process / Clipboard [options]");
System.err.println("options:");
System.err.println(" get");
System.err.println(" set 'SOME TEXT'");
System.exit(1);
}
private static void error() {
syntax();
System.exit(1);
}
private static CharSequence getClipboard() {
IInterface manager = getClipboardManager();
return getText(manager);
}
public static boolean setClipboard(CharSequence text) {
IInterface manager = getClipboardManager();
return setText(manager, text);
}
public static void main(String... args) throws Exception {
if (args.length == 0) {
error();
}
if ("get".equals(args[0])) {
if (args.length != 1) {
error();
}
System.out.println("get: " + getClipboard());
} else if ("set".equals(args[0])) {
if (args.length != 2) {
error();
}
String text = args[1];
if (setClipboard(text)) {
System.out.println("set: " + text);
} else {
System.err.println("set error");
}
} else {
error();
}
}
} Compile with: javac -source 1.7 -target 1.7 Clipboard.java -cp "$ANDROID_HOME"/platforms/android-30/android.jar
~/android/sdk/build-tools/30.0.0/dx --dex --output clipboard.dex Clipboard.class |
Did you have some time to test? |
Sorry, i've been a bit busy this week-end.
Otherwise, can you tell me how to remove the |
OK, thank you for the test 👍
|
Thanks 👍 |
Any news about a potential patch? :3 |
No, the test confirms that your device does not behave as expected. I don't have a solution for this. 😞 |
oh :c |
seconded. pls bring it back or at least make it an option |
Could you confirm that the issue only occurs with paste, but that copy works correctly: if you select a text then press Ctrl+c on the device (in the scrcpy window), could you paste it on the computer? |
Hi rom1v |
I've just implemented an option on a separate branch (
Could you please test it? For windows users, take both For other platforms, take
|
Some devices do not behave as expected when setting the device clipboard programmatically. Add an option --legacy-paste to change the behavior of Ctrl+v and MOD+v so that they inject the computer clipboard text as a sequence of key events (the same way as MOD+Shift+v). Fixes #1750 <#1750> Fixes #1771 <#1771>
Could you please test? I'm interested in knowing if it solves your problem. |
|
Yes, that's the workaround if the device Is it a better behavior? |
it's better than a buggy thing ^^ |
@rom1v Tested, working. Thank you. |
Can we get one for scrcpy-noconsole.exe too? :) |
Any new version planned with this ? |
Some devices do not behave as expected when setting the device clipboard programmatically. Add an option --legacy-paste to change the behavior of Ctrl+v and MOD+v so that they inject the computer clipboard text as a sequence of key events (the same way as MOD+Shift+v). Fixes #1750 <#1750> Fixes #1771 <#1771>
|
Also having this problem with pasting not working... I did try the legacy paste argument on the cmd line which works.. but its buggy it just leaves out characters, and doesn't even paste the whole clipboard from there pc. copy works fine.. just not pasting from the pc, Samsung note9 is there any solution to this.. I'd be fine with legacy paste if it actually pasted all the characters from the clipboard. |
scrcpy v1.17 Changes since v1.16: - Fix errors on Android 11 (Genymobile#1468) - Add --encoder option (Genymobile#1810, Genymobile#1827) - Add --forward-all-clicks option (Genymobile#1302, Genymobile#1613) - Add --legacy-paste option (Genymobile#1750, Genymobile#1771) - Workaround screen off/on issue on exit (Genymobile#1670) - Rework console/noconsole versions on Windows (Genymobile#1875, Genymobile#1988) - Terminate server properly without killing it on close (Genymobile#1992) - List available shortcut keys on error (Genymobile#1681) - Upgrade platform-tools to 30.0.5 (adb) in Windows releases - Upgrade SDL to 2.0.14 in Windows releases
@rom1v how to set multiple lines with this command? Tried with the following commands (powershell), but all of them won't work: PS > adb shell CLASSPATH=/data/local/tmp/clipboard.dex app_process / Clipboard set "line1\nline2"
set: line1nline2
PS > adb shell CLASSPATH=/data/local/tmp/clipboard.dex app_process / Clipboard set "line1\\nline2"
set: line1\nline2
PS > adb shell CLASSPATH=/data/local/tmp/clipboard.dex app_process / Clipboard set "line1\\\\nline2"
set: line1\\nline2
PS > adb shell CLASSPATH=/data/local/tmp/clipboard.dex app_process / Clipboard set "line1`nline2"
set: line1
/system/bin/sh: line2: inaccessible or not found |
This is not specific to this command, make tests with
Something like this should work: $ adb shell echo "first\\\nsecond"
first
second
$ adb shell echo "first$'\n'second"
first
second |
Thanks!
but the following works
|
Oh, sure, it works with
👍 ( |
I think we may modify the script to generate a new dex file, change: So that:
Should work. |
The new copy / paste system is not ergonomic at all .
I'd much rather paste text in "letter by letter input" mode when I press
ctrl + v
rather than having to doalt + shit + v
.And when I do
alt + v
, it pastes the text from the clipboard which is not necessarily the one I want to put.If i rebind the
mod
key toctrl
instead ofalt
, it's a real messe with copy / paste too.Can you add an option to get back to the old behavior; I use this application all day long and it's getting complicated now and I'm losing time due to errors related to copy / paste.
Thanks you
The text was updated successfully, but these errors were encountered: