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 do alt + 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 modkey to ctrlinstead of alt, 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
And when I do
alt + v, it pastes the text from the clipboard which is not necessarily the one I want to put.
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 device.setClipboardText(text) does not work on your device ROM, see #1750 (possibly because your device is rooted #1678?).
Which Android version, which Android ROM? Could you try with another device?
I've got an Samsung Galaxy S9+ and Android 10 samsung rom.
Not rooted.
But, why did you change ctrl + v to alt + v ?
But, why did you change
ctrl + vtoalt + v?
To forward the Ctrl key to the device.
See v1.15 highlights and #1598 for more details.
The new expected behavior is as described in the README: https://github.com/Genymobile/scrcpy#copy-paste
When i hit ctrl + v or alt + v, it sync the computer clipboard to the device OR if there is something in the smartphone's clipboard, it pastes it and synchronizes after pasting the old text...
Oh, wait, do you use v1.16?
Because there was a bug in v1.15: https://github.com/Genymobile/scrcpy/issues/1658
Yes, i use the v1.16 version
When i hit
ctrl + voralt + v, it sync the computer clipboard to the device OR if there is something in the smartphone's clipboard, it pastes it and synchronizes after pasting the old text...
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. :+1:
So it seems that device.setClipboardText(text) does something on the device (we see the content in the clipboard on your device), but is not pasted, neither with Ctrl+v nor Alt+v (unless the content is initially copied from the device).
You could also test adb shell input keyevent PASTE manually to paste, I guess you will have the same problem.
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 PASTE or pressing Ctrl+v should paste it.
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 adb shell input keyevent PASTE, it paste the older clipboard element, not the new one.
Github upload it's a bit buggy today, so here,s a link to the logcat.txt content : https://hastebin.com/umayuhecax.txt
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" (alt + shift + v now)
When i do
adb shell input keyevent PASTE, it paste the older clipboard element, not the new one.
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): ClipboardManager.setPrimaryClip().
I'm interested to know if you set the text from some app using this API and try to paste with adb shell input keyevent PASTE. This would allow to reproduce the problem without scrcpy.
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 don't really have the time to create an app for testing this, sorry.
However if you do one, i can test for you
I test with https://play.google.com/store/apps/details?id=devdnua.clipboard and it work when i paste the clipboard content
:confused:
I wrote a minimal scrcpy-like sample application to get and set the clipboard.
Download clipboard.dex
_SHA256: 3c7205c58c26f4ed42feda56ce3c312b13b5ff11c980817bccdc5882f629fed2_
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.
Then focus some text field on Android, and execute adb shell input keyevent PASTE to inject it.
What is the behavior?
source code
import 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.
I just tested your application and the clipboard doesn't work.
CMD :

> adb push clipboarD.dex /data/local/tmp/
clipboard.dex: 1 file pushed, 0 skipped. 1.1 MB/s (4720 bytes in 0.004s)
> adb shell CLASSPATH=/data/local/tmp/clipboard.dex app_process / Clipboard get
get: 923756
> adb shell CLASSPATH=/data/local/tmp/clipboard.dex app_process / Clipboard set abcdefgh
set: abcdefgh
> adb shell CLASSPATH=/data/local/tmp/clipboarD.dex app_process / Clipboard get
get: abcdefgh
> adb shell input keyevent PASTE
Device after PASTE event :

923756
Otherwise, can you tell me how to remove the .dex file from my phone ?
OK, thank you for the test :+1:
Otherwise, can you tell me how to remove the .dex file from my phone ?
adb shell rm /data/local/tmp/clipboard.dex
adb shell rm /data/local/tmp/clipboard.dex
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.
i'm still on 1.14 because of this. copy pasta works perfectly on 1.14 and is pretty much unusable for me on 1.16
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?
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 can confirm when I copy from scrcpy window I can paste it to PC. But copy from pc then pastes to scrcpy have issue. I'm using the latest version of scrcpy
I've just implemented an option on a separate branch (legacy_paste):
scrcpy --legacy-paste
Could you please test it?
For windows users, take both scrcpy.exe and scrcpy-server, and replace them in your scrcpy v1.16 release.
For other platforms, take scrcpy-server and build only the client.
scrcpy.exescrcpy-serverCould you please test? I'm interested in knowing if it solves your problem.
CTRL + V paste "letter by letter" now
Yes, that's the workaround if the device PASTE does not behave as expected. :+1:
Is it a better behavior?
it's better than a buggy thing ^^
Thanks !
@rom1v Tested, working. Thank you.
Can we get one for scrcpy-noconsole.exe too? :)
Any new version planned with this ?
--legacy-paste option merged into dev: d5f059c7cbef7d13889086670716d9f33f805dc4
Most helpful comment
Hi rom1v
I can confirm when I copy from scrcpy window I can paste it to PC. But copy from pc then pastes to scrcpy have issue. I'm using the latest version of scrcpy