[feat] add customizable mobile shortcuts for Windows, macOS and Linux, refs #153

This commit is contained in:
dijunkun committed 2026-11-13 16:37:55 +08:00
1 parent 72dda9bb90
commit bad4569117
47 files changed
+3314 -70

No files matched your search

@@ -321,6 +321,61 @@ final class LocalizationKeys {
IDS.put("配对信息已复制。", R.string.text_cbacf1eafbca53e0);
IDS.put("无法复制配对信息,请重试。", R.string.text_cde42ccdeacbbbd9);
IDS.put("安全存储不可用,请解锁设备后重试", R.string.text_7383b2ae09252c59);
IDS.put("上一页", R.string.text_c9b9ae7a61444ab7);
IDS.put("下一页", R.string.text_8a8542f6964852dc);
IDS.put("主按键", R.string.text_0c4f690eb398c12e);
IDS.put("任务管理器", R.string.text_62fdb5304cf5cd9b);
IDS.put("保存", R.string.text_a3030bf8f16dc63c);
IDS.put("修饰键", R.string.text_ba0e2ff8201bc6a6);
IDS.put("全选", R.string.text_3a5040b68abf75f9);
IDS.put("切换应用", R.string.text_c2d918002afcc3d4);
IDS.put("切换窗口", R.string.text_a7fe8e2685849c31);
IDS.put("剪切", R.string.text_410a8e8a6bf253ac);
IDS.put("发送组合", R.string.text_6309cd49db59d165);
IDS.put("名称", R.string.text_d44e9b3d3b31d37b);
IDS.put("向上移动", R.string.text_6789dd11afc7c4c5);
IDS.put("固定到键盘上方", R.string.text_352c003784b1c89e);
IDS.put("复制", R.string.text_63d90d977348ab1f);
IDS.put("安全选项", R.string.text_ecb0d13f3f8bfd0d);
IDS.put("已有相同组合的快捷键", R.string.text_dd1b1da65a6c89de);
IDS.put("常用", R.string.text_4563c57b5143deaa);
IDS.put("应用列表", R.string.text_6308bf1373bd0ee8);
IDS.put("强制退出面板", R.string.text_8dc0823d700cf875);
IDS.put("快捷键", R.string.text_ee2638183d3ea860);
IDS.put("我的", R.string.text_7f1d9dd04cd1c7b8);
IDS.put("按键", R.string.text_7c7577d4d4fc6009);
IDS.put("撤销", R.string.text_926a50b98ece2667);
IDS.put("新建", R.string.text_50ef2f4cf6a46924);
IDS.put("新建快捷键", R.string.text_c6904bb36f7f62c5);
IDS.put("显示桌面", R.string.text_5cfe4846aa8a7228);
IDS.put("更多快捷键", R.string.text_feb12adf8e0315e2);
IDS.put("最多保存 16 个自定义快捷键", R.string.text_5d6bce93c0649a63);
IDS.put("最多固定 8 个快捷键", R.string.text_f33cb21422f62ee8);
IDS.put("未知", R.string.text_4d8c1c5b42830791);
IDS.put("本地编辑,输入不会发送到远端", R.string.text_6b1fa1d7159de777);
IDS.put("添加到常用栏", R.string.text_cb9eaa63c25d383e);
IDS.put("移除", R.string.text_6135d4159e892541);
IDS.put("窗口菜单", R.string.text_e693ff5832c7f46d);
IDS.put("等待远端平台信息", R.string.text_096a247cc5455ba7);
IDS.put("管理与自定义", R.string.text_39c7740197c41d44);
IDS.put("管理快捷键", R.string.text_2dc8c27b75796b36);
IDS.put("粘贴", R.string.text_33517926747180e6);
IDS.put("系统", R.string.text_5b50d7c4b5950dc5);
IDS.put("终端复制", R.string.text_45123fa07e22fb3e);
IDS.put("终端粘贴", R.string.text_3936f3d30a763a35);
IDS.put("编辑", R.string.text_051836569928a9f9);
IDS.put("编辑快捷键", R.string.text_0ecda10acc934f22);
IDS.put("聚焦搜索", R.string.text_d32d2a4e0e83d7cf);
IDS.put("请使用系统预设中的安全选项", R.string.text_add54b3ce4b1c661);
IDS.put("请先选词或取消组词", R.string.text_ae066f34095261c9);
IDS.put("请输入有效的快捷键名称", R.string.text_a895bdb6f1f11e99);
IDS.put("请选择有效的按键", R.string.text_6b3213d2afed99e8);
IDS.put("运行窗口", R.string.text_819569ec77acb01e);
IDS.put("还没有自定义快捷键", R.string.text_22c4107f03c3533e);
IDS.put("适用远端", R.string.text_b07f98d4671af3f9);
IDS.put("选择桌面方案", R.string.text_4bdabfba3368869d);
IDS.put("选择桌面方案以加载系统预设", R.string.text_4fa28857c6f253cc);
IDS.put("键盘上方常用栏", R.string.text_fc5f6f7462e8557a);
}
private LocalizationKeys() {}
}
@@ -348,7 +348,7 @@ public final class MainActivity extends Activity implements NativeSession.Listen
public void togglePrivacy(){if(ready&&session!=null)session.togglePrivacy();}
public void key(int code){tapKey(code);}
public boolean textEdit(int count,String value){return sendTextEdit(count,value);}
public void chord(int code,int[] modifiers){if(session==null)return;for(int modifier:modifiers)session.key(modifier,true);tapKey(code);for(int i=modifiers.length-1;i>=0;i--)session.key(modifiers[i],false);}public void shortcut(int code){MainActivity.this.shortcut(code);}public void text(String value){sendText(value);}
public void chord(int code,int[] modifiers){if(ready&&session!=null)session.chord(code,modifiers);}public void shortcut(int code){MainActivity.this.shortcut(code);}public void text(String value){sendText(value);}
public void mute(){muted=!muted;if(session!=null)session.control(2,muted?0:1);controls.setMuted(muted);}
public void mouse(){boolean relative=!preferences.getBoolean("relativeMouse",true);preferences.edit().putBoolean("relativeMouse",relative).apply();video.setRelative(relative);controls.setRelative(relative);}
public void displayResolution(RemoteDisplayResolutions.Mode mode){updateDisplayResolution(mode);}
@@ -524,7 +524,7 @@ public final class MainActivity extends Activity implements NativeSession.Listen
toast(L10n.tr("当前远端不支持直接输入此文本,请使用支持文本输入的被控端版本,或通过剪贴板发送"));return false;
}
private void tapKey(int code){if(session!=null){session.key(code,true);session.key(code,false);}}
private void shortcut(int code){if(session!=null){int modifier=hostPlatform.equals("macos")?0x5B:0x11;session.key(modifier,true);tapKey(code);session.key(modifier,false);}}
private void shortcut(int code){if(ready&&session!=null)session.chord(code,new int[]{hostPlatform.equals("macos")?0x5B:0x11});}
private void selectDisplay(){
if(!ready)return;int count=Math.min(displays.length(),8);if(count==0){toast(L10n.tr("等待远端屏幕信息"));return;}String[] labels=new String[count];for(int i=0;i<count;i++){JSONObject display=displays.optJSONObject(i);labels[i]=(i+1)+" · "+(display==null?L10n.tr("显示器"):display.optString("name",L10n.tr("显示器")));}new AlertDialog.Builder(this).setTitle(L10n.tr("显示器")).setItems(labels,(d,w)->{if(session!=null){if(w!=selectedDisplay&&video!=null)video.resetViewport();selectedDisplay=w;session.control(4,w);if(controls!=null)controls.displayResolutions(displayResolutions,selectedDisplay);if(controls!=null)controls.resetVideoStatistics();}}).show();
}
@@ -299,6 +299,15 @@ final class NativeSession implements AutoCloseable {
void surface(Surface value) { execute(() -> { surface = value; if (handle != 0) nSurface(handle, value); }); }
void pointer(float x, float y, int flag, int wheel) { execute(() -> { if (connected) nPointer(handle, x, y, flag, wheel); }); }
void key(int code, boolean down) { execute(() -> { if (connected) nKey(handle, code, down); }); }
void chord(int code,int[] modifiers) {
if(closed||!connected)return;
int[] keys=RemoteShortcuts.normalize(modifiers);
execute(()->{
if(!connected)return;
try{for(int modifier:keys)nKey(handle,modifier,true);nKey(handle,code,true);}
finally{nKey(handle,code,false);for(int i=keys.length-1;i>=0;i--)nKey(handle,keys[i],false);}
});
}
boolean textEdit(int deletions,String text) {
byte[] bytes=text.getBytes(StandardCharsets.UTF_8);
boolean unicode=supportsTextInput;
@@ -22,6 +22,12 @@ final class RemoteKeyboard extends LinearLayout {
private final Runnable changed;
private final LinearLayout toolbar,keys;
private final TextView switchButton,lettersButton,functionsButton;
private final LinearLayout quickKeys;
private final HorizontalScrollView quickScroll;
private final TextView panelTitle;
private final RemoteShortcutPanel shortcutPanel;
private String hostPlatform="unknown";
private boolean shortcuts;
private final Set<Integer> modifiers=new LinkedHashSet<>();
private final SparseIntArray heights=new SparseIntArray();
private boolean opened,computer,functions,imeVisible,measuring,switching,targetComputer;
@@ -35,15 +41,20 @@ final class RemoteKeyboard extends LinearLayout {
public boolean edit(int count,String text){return actions.textEdit(count,text);}
public void key(int code){actions.key(code);}
});
shortcutPanel=new RemoteShortcutPanel(context,ui,this::sendShortcut,()->{render();changed.run();});
FrameLayout header=new FrameLayout(context);addView(header,new LayoutParams(-1,ui.dp(44)));
header.addView(editor,new FrameLayout.LayoutParams(1,1,Gravity.BOTTOM));
toolbar=ui.row();toolbar.setGravity(Gravity.CENTER_VERTICAL);toolbar.setPadding(ui.dp(6),0,ui.dp(6),0);
header.addView(toolbar,new FrameLayout.LayoutParams(-1,-1));
switchButton=button(L10n.tr("电脑键盘"),this::switchKeyboard);switchButton.setPadding(ui.dp(8),0,ui.dp(8),0);
switchButton=button(L10n.tr("电脑键盘"),()->{shortcuts=false;switchKeyboard();});switchButton.setPadding(ui.dp(8),0,ui.dp(8),0);
toolbar.addView(switchButton,new LayoutParams(-2,-1));
LinearLayout pages=ui.row();pages.setGravity(Gravity.CENTER);toolbar.addView(pages,new LayoutParams(0,-1,1));
quickScroll=new HorizontalScrollView(context);quickScroll.setHorizontalScrollBarEnabled(false);
quickKeys=ui.row();quickScroll.addView(quickKeys);pages.addView(quickScroll,new LayoutParams(-1,-1));
panelTitle=ui.text(L10n.tr("快捷键"),13,false);panelTitle.setGravity(Gravity.CENTER);pages.addView(panelTitle,new LayoutParams(-1,-1));
lettersButton=button(L10n.tr("字母数字"),()->page(false));functionsButton=button(L10n.tr("符号功能"),()->page(true));
pages.addView(lettersButton,new LayoutParams(-2,ui.dp(32)));pages.addView(functionsButton,new LayoutParams(-2,ui.dp(32)));
TextView more=button("⋯",this::showShortcuts);more.setContentDescription(L10n.tr("更多快捷键"));toolbar.addView(more,new LayoutParams(ui.dp(44),ui.dp(44)));
FrameLayout hide=new FrameLayout(context);hide.setContentDescription(L10n.tr("收起键盘"));hide.setClickable(true);hide.setFocusable(true);
hide.addView(ui.icon("keyboard_hide",foreground()),new FrameLayout.LayoutParams(ui.dp(24),ui.dp(24),Gravity.CENTER));
hide.setOnClickListener(v->{feedback(v);close();});toolbar.addView(hide,new LayoutParams(ui.dp(44),ui.dp(44)));
@@ -60,6 +71,7 @@ final class RemoteKeyboard extends LinearLayout {
private void feedback(View view){view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);}
boolean isOpen(){return opened;}
boolean isComputer(){return computer;}
void setPlatform(String value){hostPlatform=RemoteShortcuts.platform(value);shortcutPanel.platform(hostPlatform);if(opened)render();}
int bottomInset(){return opened&&!computer?imeHeight:0;}
private int sizeKey(){Configuration c=getResources().getConfiguration();return c.screenWidthDp*10000+c.screenHeightDp;}
private int keyAreaHeight(){
@@ -71,11 +83,11 @@ final class RemoteKeyboard extends LinearLayout {
int preferredHeight(){return ui.dp(44)+(computer?keyAreaHeight():0);}
void toggle(){if(opened)close();else open();}
void open(){
opened=true;computer=false;modifiers.clear();editor.start();setVisibility(VISIBLE);render();changed.run();
opened=true;computer=shortcuts=false;modifiers.clear();editor.start();setVisibility(VISIBLE);render();changed.run();
post(()->{if(opened&&!computer)changeIme(true,false,false);});
}
boolean close(){
if(!opened)return false;opened=false;measuring=switching=false;cancelTransition();modifiers.clear();editor.stop();
shortcutPanel.close();if(!opened)return false;opened=false;measuring=switching=false;cancelTransition();modifiers.clear();editor.stop();
getContext().getSystemService(InputMethodManager.class).hideSoftInputFromWindow(getWindowToken(),0);
setVisibility(GONE);changed.run();return true;
}
@@ -83,6 +95,7 @@ final class RemoteKeyboard extends LinearLayout {
private void page(boolean next){functions=next;render();}
private void switchKeyboard(){
if(!opened||switching)return;
if(!computer&&!prepareShortcut())return;
targetComputer=!computer;switching=true;modifiers.clear();
if(targetComputer){
editor.pause();computer=true;render();changed.run();
@@ -99,6 +112,20 @@ final class RemoteKeyboard extends LinearLayout {
invalidate();
}else changeIme(!targetComputer,true,false);
}
private boolean prepareShortcut(){
if(computer)return true;
if(editor.hasPendingComposition()){Toast.makeText(getContext(),L10n.tr("请先选词或取消组词"),Toast.LENGTH_SHORT).show();return false;}
return editor.prepareShortcut();
}
private void showShortcuts(){
if(!opened||switching)return;
if(computer){if(shortcuts)switchKeyboard();else{shortcuts=true;modifiers.clear();render();changed.run();}}
else{shortcuts=true;switchKeyboard();}
}
private void sendShortcut(RemoteShortcuts.Item item){
if(!opened||switching||!item.platform.equals(hostPlatform)||!prepareShortcut())return;
modifiers.clear();if(item.service)actions.secureAttention();else actions.chord(item.key,item.modifiers);
}
private void finishSwitch(){
if(!switching)return;switching=false;
if(computer!=targetComputer){computer=targetComputer;render();}
@@ -158,7 +185,9 @@ final class RemoteKeyboard extends LinearLayout {
private void render(){
setBackgroundColor(dark()?0xFF202124:0xFFE8EAED);
switchButton.setText(computer?L10n.tr("系统键盘"):L10n.tr("电脑键盘"));switchButton.setTextColor(foreground());
lettersButton.setVisibility(computer?VISIBLE:GONE);functionsButton.setVisibility(computer?VISIBLE:GONE);
lettersButton.setVisibility(computer&&!shortcuts?VISIBLE:GONE);functionsButton.setVisibility(computer&&!shortcuts?VISIBLE:GONE);
quickScroll.setVisibility(computer?GONE:VISIBLE);panelTitle.setVisibility(computer&&shortcuts?VISIBLE:GONE);panelTitle.setTextColor(foreground());
quickKeys.removeAllViews();for(RemoteShortcuts.Item item:shortcutPanel.store.pinned(hostPlatform)){TextView key=button(item.title(),()->sendShortcut(item));key.setContentDescription(item.title()+", "+item.chord());quickKeys.addView(key,new LayoutParams(-2,ui.dp(44)));}
for(TextView view:new TextView[]{lettersButton,functionsButton}){
boolean selected=(view==functionsButton)==functions;view.setSelected(selected);
view.setTextColor(selected?(dark()?0xFFA8C7FA:0xFF185ABC):foreground());
@@ -169,6 +198,7 @@ final class RemoteKeyboard extends LinearLayout {
private void renderKeysIfNeeded(int width){
if(!computer)return;int height=keyAreaHeight();
if(layoutWidth==width&&layoutHeight==height)return;layoutWidth=width;layoutHeight=height;keys.removeAllViews();
if(shortcuts){keys.addView(shortcutPanel.create(),new LayoutParams(-1,-1));return;}
boolean landscape=getResources().getConfiguration().screenWidthDp>getResources().getConfiguration().screenHeightDp;
String[][] upper;
if(!functions)upper=new String[][]{{"1","2","3","4","5","6","7","8","9","0"},{"q","w","e","r","t","y","u","i","o","p"},{"a","s","d","f","g","h","j","k","l"}};
@@ -185,6 +215,7 @@ final class RemoteKeyboard extends LinearLayout {
LinearLayout line=ui.row();line.setGravity(Gravity.CENTER);
for(String value:values){
boolean shift=modifiers.contains(16);String shown=shift&&value.length()==1?shifted(value):value;
if(value.equals("Win"))shown=RemoteShortcuts.modifierName(91,hostPlatform);else if(value.equals("Alt"))shown=RemoteShortcuts.modifierName(18,hostPlatform);
TextView key=button(L10n.tr(shown),()->key(value));key.setPadding(0,0,0,0);
key.setTextSize(value.length()>1?12:18);key.setSingleLine(true);
int modifier=modifier(value);boolean selected=modifier!=0&&modifiers.contains(modifier);key.setSelected(selected);
@@ -209,6 +240,7 @@ final class RemoteKeyboard extends LinearLayout {
int modifier=modifier(value);if(modifier!=0){if(!modifiers.add(modifier))modifiers.remove(modifier);render();return;}
int code=switch(value){case "空格"->32;case "Enter"->13;case "⌫"->8;case "Esc"->27;case "Tab"->9;case "Caps"->20;case "Ins"->45;case "Del"->46;case "Home"->36;case "End"->35;case "PgUp"->33;case "PgDn"->34;case "←"->37;case "↑"->38;case "→"->39;case "↓"->40;default->value.startsWith("F")?111+Integer.parseInt(value.substring(1)):KeyMap.ascii(value.charAt(0))&255;};
actions.chord(code,modifiers.stream().mapToInt(Integer::intValue).toArray());
modifiers.clear();render();
}
@Override protected void onMeasure(int widthSpec,int heightSpec){
renderKeysIfNeeded(MeasureSpec.getSize(widthSpec));super.onMeasure(widthSpec,heightSpec);
@@ -52,6 +52,15 @@ final class RemoteKeyboardInput extends EditText {
void pause() { accepting=false;resetContext(); }
void stop() { pause();clearFocus(); }
boolean isAcceptingInput() { return accepting; }
boolean hasPendingComposition() { return batches>0||composing(); }
boolean prepareShortcut() {
if(!synchronize())return false;
// Navigation and shortcuts invalidate the remote correction context.
// Flush committed text first; never send or discard an IME preedit.
if(enterPending)sender.key(13);
resetContext();
return true;
}
void resetContext() {
generation++;batches=0;main.removeCallbacks(synchronize);resetting=true;
// EditText.setText replaces the buffer and internally restarts the IME,
@@ -0,0 +1,107 @@
package cn.crossdesk.mobile;
import android.app.Dialog;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Color;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
/** The preset panel occupies the keyboard keybed; editing uses a separate local window. */
final class RemoteShortcutPanel {
private final Context context;
private final MobileUi ui;
final RemoteShortcuts store;
private final Consumer<RemoteShortcuts.Item> send;
private final Runnable changed;
private String platform="unknown";
private int category,page;
private Dialog manager;
RemoteShortcutPanel(Context context,MobileUi ui,Consumer<RemoteShortcuts.Item> send,Runnable changed){this.context=context;this.ui=ui;this.send=send;this.changed=changed;store=new RemoteShortcuts(context);}
void platform(String value){String next=RemoteShortcuts.platform(value);if(!platform.equals(next)){platform=next;page=0;close();}}
private void hideEditor(){if(manager!=null&&manager.getWindow()!=null)context.getSystemService(android.view.inputmethod.InputMethodManager.class).hideSoftInputFromWindow(manager.getWindow().getDecorView().getWindowToken(),0);}
void close(){if(manager!=null){hideEditor();manager.dismiss();manager=null;}}
private boolean dark(){return (context.getResources().getConfiguration().uiMode&Configuration.UI_MODE_NIGHT_MASK)==Configuration.UI_MODE_NIGHT_YES;}
private int ink(){return dark()?Color.WHITE:0xFF202124;}
private int surface(){return dark()?0xFF202124:0xFFF1F3F6;}
private TextView text(String value,int size){TextView text=ui.text(value,size,false);text.setTextColor(ink());return text;}
private TextView button(String value,Runnable action){TextView button=ui.action(value,ink(),action);button.setTextSize(13);button.setMinHeight(ui.dp(44));button.setPadding(ui.dp(8),0,ui.dp(8),0);return button;}
private void refresh(){changed.run();}
View create(){
LinearLayout root=ui.column();root.setPadding(ui.dp(6),0,ui.dp(6),0);
String[] groups={"common","keys","system","mine"},labels={L10n.tr("常用"),L10n.tr("按键"),L10n.tr("系统"),L10n.tr("我的")};
root.addView(new SegmentedControl(ui,labels,category,true,index->{category=index;page=0;refresh();}),new LinearLayout.LayoutParams(-1,ui.dp(36)));
if(category==2&&platform.equals("linux")){
Spinner desktop=spinner(new String[]{L10n.tr("选择桌面方案"),"GNOME","KDE Plasma"},store.desktop().equals("gnome")?1:store.desktop().equals("kde")?2:0,index->{String next=index==1?"gnome":index==2?"kde":"";if(!store.desktop().equals(next)){store.desktop(next);page=0;refresh();}});
root.addView(desktop,new LinearLayout.LayoutParams(-1,ui.dp(40)));
}
List<RemoteShortcuts.Item> items=new ArrayList<>();for(RemoteShortcuts.Item item:store.items(platform))if(item.group.equals(groups[category]))items.add(item);
int count=Math.max(1,(items.size()+5)/6);page=Math.min(page,count-1);
ScrollView gridScroll=new ScrollView(context);gridScroll.setFillViewport(true);root.addView(gridScroll,new LinearLayout.LayoutParams(-1,0,1));
LinearLayout grid=ui.column();grid.setMinimumHeight(ui.dp(items.isEmpty()?44:108));gridScroll.addView(grid,new FrameLayout.LayoutParams(-1,-2));
if(items.isEmpty()){TextView empty=text(L10n.tr(platform.equals("unknown")?"等待远端平台信息":category==2?"选择桌面方案以加载系统预设":"还没有自定义快捷键"),13);empty.setGravity(Gravity.CENTER);grid.addView(empty,new LinearLayout.LayoutParams(-1,-1));}
else for(int row=0;row<2;row++){
LinearLayout line=ui.row();for(int col=0;col<3;col++){
int index=page*6+row*3+col;LinearLayout.LayoutParams params=new LinearLayout.LayoutParams(0,-1,1);params.setMargins(ui.dp(3),ui.dp(3),ui.dp(3),ui.dp(3));
if(index>=items.size()){line.addView(new View(context),params);continue;}
RemoteShortcuts.Item item=items.get(index);LinearLayout tile=ui.column();tile.setGravity(Gravity.CENTER);tile.setPadding(ui.dp(3),0,ui.dp(3),0);tile.setBackground(ui.background(dark()?0xFF353A43:Color.WHITE,7));
TextView name=text(item.title(),13);name.setGravity(Gravity.CENTER);name.setMaxLines(2);tile.addView(name);TextView chord=text(item.chord(),11);chord.setGravity(Gravity.CENTER);chord.setMaxLines(2);tile.addView(chord);
tile.setContentDescription(item.title()+", "+item.chord());tile.setClickable(true);tile.setFocusable(true);tile.setOnClickListener(v->send.accept(item));line.addView(tile,params);
}grid.addView(line,new LinearLayout.LayoutParams(-1,0,1));
}
LinearLayout footer=ui.row();footer.setGravity(Gravity.CENTER_VERTICAL);
if(count>1){TextView previous=button("‹",()->{page--;refresh();});previous.setEnabled(page>0);previous.setContentDescription(L10n.tr("上一页"));footer.addView(previous);footer.addView(text((page+1)+" / "+count,12));TextView next=button("›",()->{page++;refresh();});next.setEnabled(page+1<count);next.setContentDescription(L10n.tr("下一页"));footer.addView(next);}
else footer.addView(text(RemoteShortcuts.platformName(platform),12));
footer.addView(new View(context),new LinearLayout.LayoutParams(0,1,1));TextView edit=button(L10n.tr("管理与自定义"),this::manage);edit.setEnabled(!platform.equals("unknown"));footer.addView(edit);root.addView(footer,new LinearLayout.LayoutParams(-1,ui.dp(44)));
return root;
}
private Spinner spinner(String[] labels,int selected,Consumer<Integer> changed){Spinner spinner=new Spinner(context);ArrayAdapter<String> adapter=new ArrayAdapter<>(context,android.R.layout.simple_spinner_dropdown_item,labels);spinner.setAdapter(adapter);spinner.setSelection(selected);spinner.setOnItemSelectedListener(new android.widget.AdapterView.OnItemSelectedListener(){public void onNothingSelected(android.widget.AdapterView<?> p){}public void onItemSelected(android.widget.AdapterView<?> p,View v,int position,long id){changed.accept(position);}});return spinner;}
private LinearLayout screen(String title,Runnable back,String action,Runnable submit){
LinearLayout root=ui.column();root.setBackgroundColor(surface());LinearLayout header=ui.row();header.setGravity(Gravity.CENTER_VERTICAL);header.addView(button(L10n.tr("返回"),back));TextView heading=text(title,17);header.addView(heading,new LinearLayout.LayoutParams(0,-2,1));if(action!=null)header.addView(button(action,submit));root.addView(header,new LinearLayout.LayoutParams(-1,ui.dp(52)));
TextView note=text(L10n.tr("本地编辑,输入不会发送到远端"),12);note.setPadding(ui.dp(16),ui.dp(8),ui.dp(16),ui.dp(8));root.addView(note);return root;
}
private LinearLayout scrollBody(LinearLayout root){ScrollView scroll=new ScrollView(context);root.addView(scroll,new LinearLayout.LayoutParams(-1,0,1));LinearLayout body=ui.column();body.setPadding(ui.dp(16),ui.dp(8),ui.dp(16),ui.dp(20));scroll.addView(body);return body;}
private void present(View root){
if(manager==null){manager=new Dialog(context);manager.requestWindowFeature(Window.FEATURE_NO_TITLE);manager.setOnDismissListener(d->{manager=null;refresh();});}
hideEditor();manager.setContentView(root);manager.show();Window window=manager.getWindow();if(window!=null){window.setLayout(-1,-1);window.setBackgroundDrawableResource(android.R.color.transparent);window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);}
}
private void manage(){
LinearLayout root=screen(L10n.tr("管理快捷键"),this::close,L10n.tr("新建"),()->edit(null));LinearLayout body=scrollBody(root);body.addView(text(RemoteShortcuts.platformName(platform)+" · "+L10n.tr("键盘上方常用栏"),14));
List<String> selected=store.pins(platform);
for(RemoteShortcuts.Item item:store.pinned(platform)){
LinearLayout row=ui.row();row.setGravity(Gravity.CENTER_VERTICAL);TextView label=text(item.title()+"\n"+item.chord(),13);row.addView(label,new LinearLayout.LayoutParams(0,-2,1));
TextView up=button("↑",()->{List<String> list=store.pins(platform);int index=list.indexOf(item.id);if(index>0){java.util.Collections.swap(list,index,index-1);store.pins(platform,list);manage();}});up.setContentDescription(L10n.tr("向上移动"));up.setEnabled(selected.indexOf(item.id)>0);row.addView(up);
row.addView(button(L10n.tr("移除"),()->{List<String> list=store.pins(platform);list.remove(item.id);store.pins(platform,list);manage();}));body.addView(row);ui.divider(body);
}
ui.gap(body,16);body.addView(text(L10n.tr("添加到常用栏"),14));
for(RemoteShortcuts.Item item:store.items(platform)){
LinearLayout row=ui.row();row.setGravity(Gravity.CENTER_VERTICAL);TextView label=text(item.title()+"\n"+item.chord(),13);row.addView(label,new LinearLayout.LayoutParams(0,-2,1));
if(!selected.contains(item.id))row.addView(button("+",()->{List<String> list=store.pins(platform);if(list.size()>=RemoteShortcuts.MAX_PINNED){Toast.makeText(context,L10n.tr("最多固定 8 个快捷键"),Toast.LENGTH_SHORT).show();return;}list.add(item.id);store.pins(platform,list);manage();}));
if(item.custom){row.addView(button(L10n.tr("编辑"),()->edit(item)));row.addView(button(L10n.tr("删除"),()->{store.remove(item.id);manage();}));}
body.addView(row);
}
present(root);
}
private void edit(RemoteShortcuts.Item existing){
EditText name=new EditText(context);name.setTextColor(ink());name.setSingleLine();name.setText(existing==null?"":existing.name);name.setHint(L10n.tr("名称"));name.setFilters(new android.text.InputFilter[]{new android.text.InputFilter.LengthFilter(64)});
final String[] target={existing==null?platform:existing.platform};final int[] key={existing==null?83:existing.key};List<Integer> modifiers=new ArrayList<>();for(int code:existing==null?new int[]{platform.equals("macos")?91:17}:existing.modifiers)modifiers.add(code);
CheckBox pin=new CheckBox(context);pin.setTextColor(ink());pin.setText(L10n.tr("固定到键盘上方"));pin.setChecked(existing==null?store.pins(target[0]).size()<RemoteShortcuts.MAX_PINNED:store.pins(existing.platform).contains(existing.id));
TextView error=text("",13);error.setTextColor(0xFFE45757);TextView preview=text("",16);
Runnable update=()->preview.setText(new RemoteShortcuts.Item("","",target[0],"mine",key[0],RemoteShortcuts.normalize(modifiers.stream().mapToInt(Integer::intValue).toArray()),false,true).chord());
LinearLayout root=screen(L10n.tr(existing==null?"新建快捷键":"编辑快捷键"),this::manage,L10n.tr("保存"),()->{String result=store.save(existing==null?null:existing.id,name.getText().toString(),target[0],key[0],modifiers.stream().mapToInt(Integer::intValue).toArray(),pin.isChecked());if(result.isEmpty())manage();else error.setText(result);});
LinearLayout body=scrollBody(root);body.addView(name,new LinearLayout.LayoutParams(-1,ui.dp(52)));ui.gap(body,12);
LinearLayout modifierRow=ui.row();CheckBox[] toggles=new CheckBox[4];for(int i=0;i<4;i++){final int code=RemoteShortcuts.MODIFIERS[i];CheckBox toggle=new CheckBox(context);toggle.setTextColor(ink());toggle.setTextSize(12);toggle.setText(RemoteShortcuts.modifierName(code,target[0]));toggle.setChecked(modifiers.contains(code));toggle.setOnCheckedChangeListener((v,checked)->{if(checked){if(!modifiers.contains(code))modifiers.add(code);}else modifiers.remove(Integer.valueOf(code));update.run();});toggles[i]=toggle;modifierRow.addView(toggle,new LinearLayout.LayoutParams(0,ui.dp(48),1));}
List<Integer> keys=RemoteShortcuts.keys();
Spinner mainKey=spinner(keys.stream().map(code->RemoteShortcuts.keyName(code,target[0])).toArray(String[]::new),keys.indexOf(key[0]),index->{key[0]=keys.get(index);update.run();});
body.addView(text(L10n.tr("适用远端"),13));body.addView(spinner(new String[]{"Windows","macOS","Linux"},Arrays.asList(RemoteShortcuts.PLATFORMS).indexOf(target[0]),index->{target[0]=RemoteShortcuts.PLATFORMS[index];mainKey.setAdapter(new ArrayAdapter<>(context,android.R.layout.simple_spinner_dropdown_item,keys.stream().map(code->RemoteShortcuts.keyName(code,target[0])).toArray(String[]::new)));mainKey.setSelection(keys.indexOf(key[0]));for(int i=0;i<4;i++)toggles[i].setText(RemoteShortcuts.modifierName(RemoteShortcuts.MODIFIERS[i],target[0]));update.run();}),new LinearLayout.LayoutParams(-1,ui.dp(48)));
body.addView(text(L10n.tr("主按键"),13));body.addView(mainKey,new LinearLayout.LayoutParams(-1,ui.dp(48)));
body.addView(text(L10n.tr("修饰键"),13));body.addView(modifierRow);body.addView(text(L10n.tr("发送组合"),13));body.addView(preview);body.addView(pin);body.addView(error);update.run();present(root);
}
}
@@ -0,0 +1,99 @@
package cn.crossdesk.mobile;
import android.content.Context;
import android.content.SharedPreferences;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
/** Local controller preferences. Key codes use the existing cross-platform wire mapping. */
final class RemoteShortcuts {
static final int MAX_CUSTOM=16,MAX_PINNED=8;
static final String[] PLATFORMS={"windows","macos","linux"};
static final int[] MODIFIERS={17,16,18,91};
static final class Item {
final String id,name,platform,group;
final int key;
final int[] modifiers;
final boolean service,custom;
Item(String id,String name,String platform,String group,int key,int[] modifiers,boolean service,boolean custom){
this.id=id;this.name=name;this.platform=platform;this.group=group;this.key=key;
this.modifiers=modifiers.clone();this.service=service;this.custom=custom;
}
String title(){return custom?name:L10n.tr(name);}
String chord(){List<String> parts=new ArrayList<>();for(int modifier:modifiers)parts.add(modifierName(modifier,platform));parts.add(keyName(key,platform));return String.join(" + ",parts);}
}
private final SharedPreferences preferences;
RemoteShortcuts(Context context){preferences=context.getSharedPreferences("remote_shortcuts_v1",Context.MODE_PRIVATE);}
static String platform(String value){return Arrays.asList(PLATFORMS).contains(value)?value:"unknown";}
static String platformName(String value){return switch(value){case "windows"->"Windows";case "macos"->"macOS";case "linux"->"Linux";default->L10n.tr("未知");};}
String desktop(){String value=preferences.getString("linux_desktop","");return value.equals("gnome")||value.equals("kde")?value:"";}
void desktop(String value){preferences.edit().putString("linux_desktop",value.equals("gnome")||value.equals("kde")?value:"").apply();}
static String modifierName(int code,String platform){return switch(code){case 17->"Ctrl";case 16->"Shift";case 18->platform.equals("macos")?"Option":"Alt";case 91->platform.equals("macos")?"Cmd":platform.equals("linux")?"Super":"Win";default->"";};}
static String keyName(int code,String platform){
if(code>=65&&code<=90||code>=48&&code<=57)return Character.toString((char)code);
if(code>=112&&code<=123)return "F"+(code-111);
return switch(code){case 8->platform.equals("macos")?"Delete ⌫":"Backspace";case 9->"Tab";case 13->"Enter";case 27->"Esc";case 32->"Space";case 33->"PageUp";case 34->"PageDown";case 35->"End";case 36->"Home";case 37->"←";case 38->"↑";case 39->"→";case 40->"↓";case 45->"Insert";case 46->platform.equals("macos")?"Delete ⌦":"Delete";default->"";};
}
static List<Integer> keys(){List<Integer> result=new ArrayList<>();for(int i=65;i<=90;i++)result.add(i);for(int i=48;i<=57;i++)result.add(i);for(int i=112;i<=123;i++)result.add(i);for(int i:new int[]{27,9,13,32,8,46,45,36,35,33,34,37,38,39,40})result.add(i);return result;}
static int[] normalize(int[] modifiers){return Arrays.stream(MODIFIERS).filter(code->Arrays.stream(modifiers).anyMatch(value->value==code)).toArray();}
private static Item preset(String id,String name,String platform,String group,int key,int... modifiers){return new Item(id,name,platform,group,key,modifiers,false,false);}
List<Item> items(String remote){
String os=platform(remote);List<Item> result=new ArrayList<>();
if(!os.equals("unknown")){
int primary=os.equals("macos")?91:17;
String[] ids={"copy","paste","cut","all","undo","save"},names={"复制","粘贴","剪切","全选","撤销","保存"};int[] keys={67,86,88,65,90,83};
for(int i=0;i<ids.length;i++)result.add(preset(ids[i],names[i],os,"common",keys[i],primary));
if(os.equals("linux")){result.add(preset("term-copy","终端复制",os,"common",67,17,16));result.add(preset("term-paste","终端粘贴",os,"common",86,17,16));}
}
for(int key:new int[]{27,9,13,8,46,36,35,33,34,37,38,39,40,112,113,114,115,116,117,118,119,120,121,122,123})
result.add(preset(key==27?"esc":key==9?"tab":"key-"+key,keyName(key,os),os,"keys",key));
if(os.equals("windows")){
result.add(preset("switch","切换窗口",os,"system",9,18));result.add(preset("desktop","显示桌面",os,"system",68,91));result.add(preset("task","任务管理器",os,"system",27,17,16));
result.add(new Item("sas","安全选项",os,"system",46,new int[]{17,18},true,false));
}else if(os.equals("macos")){
result.add(preset("switch","切换应用",os,"system",9,91));result.add(preset("search","聚焦搜索",os,"system",32,91));result.add(preset("forcequit","强制退出面板",os,"system",27,18,91));
}else if(os.equals("linux")&&!desktop().isEmpty()){
result.add(preset("switch",desktop().equals("gnome")?"切换应用":"切换窗口",os,"system",9,desktop().equals("gnome")?91:18));result.add(preset("run","运行窗口",os,"system",113,18));
result.add(desktop().equals("gnome")?preset("apps","应用列表",os,"system",65,91):preset("window-menu","窗口菜单",os,"system",114,18));
}
for(Item item:custom())if(item.platform.equals(os))result.add(item);
return result;
}
List<Item> custom(){
List<Item> result=new ArrayList<>();
try{JSONArray entries=new JSONArray(preferences.getString("custom","[]"));for(int i=0;i<entries.length()&&result.size()<MAX_CUSTOM;i++){
JSONObject entry=entries.optJSONObject(i);if(entry==null)continue;String os=platform(entry.optString("platform")),id=entry.optString("id"),name=entry.optString("name").trim();int key=entry.optInt("key");JSONArray modifiers=entry.optJSONArray("modifiers");
if(os.equals("unknown")||!id.startsWith("custom-")||name.isEmpty()||name.length()>64||!keys().contains(key)||modifiers==null||modifiers.length()>4)continue;
int[] values=new int[modifiers.length()];boolean valid=true;for(int j=0;j<values.length;j++){int value=modifiers.optInt(j);values[j]=value;if(!Arrays.stream(MODIFIERS).anyMatch(code->code==value))valid=false;}
if(!valid)continue;int[] normalized=normalize(values);if(os.equals("windows")&&key==46&&Arrays.stream(normalized).anyMatch(v->v==17)&&Arrays.stream(normalized).anyMatch(v->v==18))continue;
if(result.stream().anyMatch(item->item.id.equals(id)))continue;
result.add(new Item(id,name,os,"mine",key,normalized,false,true));
}}catch(Exception ignored){ }
return result;
}
List<String> pins(String os){
List<String> result=new ArrayList<>();String stored=preferences.getString("pins_"+platform(os),null);
if(stored==null)stored="[\"esc\",\"tab\",\"copy\",\"paste\"]";
try{JSONArray array=new JSONArray(stored);for(int i=0;i<array.length()&&result.size()<MAX_PINNED;i++){String id=array.optString(i);if(!id.isEmpty()&&!result.contains(id))result.add(id);}}catch(Exception ignored){result.addAll(Arrays.asList("esc","tab","copy","paste"));}
List<Item> available=items(os);result.removeIf(id->available.stream().noneMatch(item->item.id.equals(id)));
return result;
}
List<Item> pinned(String os){List<Item> all=items(os),result=new ArrayList<>();for(String id:pins(os))for(Item item:all)if(item.id.equals(id)){result.add(item);break;}return result;}
void pins(String os,List<String> values){preferences.edit().putString("pins_"+platform(os),new JSONArray(values.subList(0,Math.min(values.size(),MAX_PINNED))).toString()).apply();}
void remove(String id){List<Item> values=custom();values.removeIf(item->item.id.equals(id));write(values);for(String os:PLATFORMS){List<String> selected=pins(os);selected.remove(id);pins(os,selected);}}
String save(String id,String name,String os,int key,int[] modifiers,boolean pin){
name=name.trim();if(name.isEmpty()||name.length()>64)return L10n.tr("请输入有效的快捷键名称");
if(platform(os).equals("unknown")||!keys().contains(key))return L10n.tr("请选择有效的按键");
int[] normalized=normalize(modifiers);if(os.equals("windows")&&key==46&&Arrays.stream(normalized).anyMatch(v->v==17)&&Arrays.stream(normalized).anyMatch(v->v==18))return L10n.tr("请使用系统预设中的安全选项");
List<Item> values=custom();boolean exists=false;for(Item item:values){if(item.id.equals(id))exists=true;else if(item.platform.equals(os)&&item.key==key&&Arrays.equals(item.modifiers,normalized))return L10n.tr("已有相同组合的快捷键");}
if(!exists&&values.size()>=MAX_CUSTOM)return L10n.tr("最多保存 16 个自定义快捷键");
List<String> selected=pins(os);if(pin&&!selected.contains(id)&&selected.size()>=MAX_PINNED)return L10n.tr("最多固定 8 个快捷键");
String itemId=id==null?"custom-"+UUID.randomUUID():id;values.removeIf(item->item.id.equals(itemId));values.add(new Item(itemId,name,os,"mine",key,normalized,false,true));write(values);
for(String target:PLATFORMS){List<String> list=pins(target);int index=list.indexOf(itemId);list.remove(itemId);if(target.equals(os)&&pin)list.add(index>=0?Math.min(index,list.size()):list.size(),itemId);pins(target,list);}return "";
}
private void write(List<Item> items){JSONArray array=new JSONArray();try{for(Item item:items){JSONArray modifiers=new JSONArray();for(int code:item.modifiers)modifiers.put(code);array.put(new JSONObject().put("id",item.id).put("name",item.name).put("platform",item.platform).put("key",item.key).put("modifiers",modifiers));}}catch(Exception ignored){return;}preferences.edit().putString("custom",array.toString()).apply();}
}
@@ -72,6 +72,7 @@ final class SessionControls extends FrameLayout {
}
void setRelative(boolean value){relative=value;if(menu!=null&&menuPage.equals("controls"))openMenu("controls");}
void setHostPlatform(String platform){
keyboard.setPlatform(platform);
boolean visible="windows".equals(platform);
if(secureAttentionVisible==visible)return;
secureAttentionVisible=visible;
@@ -315,4 +315,59 @@
<string name="text_cbacf1eafbca53e0" formatted="false">"配对信息已复制。"</string>
<string name="text_cde42ccdeacbbbd9" formatted="false">"无法复制配对信息,请重试。"</string>
<string name="text_7383b2ae09252c59" formatted="false">"安全存储不可用,请解锁设备后重试"</string>
<string name="text_c9b9ae7a61444ab7" formatted="false">"上一页"</string>
<string name="text_8a8542f6964852dc" formatted="false">"下一页"</string>
<string name="text_0c4f690eb398c12e" formatted="false">"主按键"</string>
<string name="text_62fdb5304cf5cd9b" formatted="false">"任务管理器"</string>
<string name="text_a3030bf8f16dc63c" formatted="false">"保存"</string>
<string name="text_ba0e2ff8201bc6a6" formatted="false">"修饰键"</string>
<string name="text_3a5040b68abf75f9" formatted="false">"全选"</string>
<string name="text_c2d918002afcc3d4" formatted="false">"切换应用"</string>
<string name="text_a7fe8e2685849c31" formatted="false">"切换窗口"</string>
<string name="text_410a8e8a6bf253ac" formatted="false">"剪切"</string>
<string name="text_6309cd49db59d165" formatted="false">"发送组合"</string>
<string name="text_d44e9b3d3b31d37b" formatted="false">"名称"</string>
<string name="text_6789dd11afc7c4c5" formatted="false">"向上移动"</string>
<string name="text_352c003784b1c89e" formatted="false">"固定到键盘上方"</string>
<string name="text_63d90d977348ab1f" formatted="false">"复制"</string>
<string name="text_ecb0d13f3f8bfd0d" formatted="false">"安全选项"</string>
<string name="text_dd1b1da65a6c89de" formatted="false">"已有相同组合的快捷键"</string>
<string name="text_4563c57b5143deaa" formatted="false">"常用"</string>
<string name="text_6308bf1373bd0ee8" formatted="false">"应用列表"</string>
<string name="text_8dc0823d700cf875" formatted="false">"强制退出面板"</string>
<string name="text_ee2638183d3ea860" formatted="false">"快捷键"</string>
<string name="text_7f1d9dd04cd1c7b8" formatted="false">"我的"</string>
<string name="text_7c7577d4d4fc6009" formatted="false">"按键"</string>
<string name="text_926a50b98ece2667" formatted="false">"撤销"</string>
<string name="text_50ef2f4cf6a46924" formatted="false">"新建"</string>
<string name="text_c6904bb36f7f62c5" formatted="false">"新建快捷键"</string>
<string name="text_5cfe4846aa8a7228" formatted="false">"显示桌面"</string>
<string name="text_feb12adf8e0315e2" formatted="false">"更多快捷键"</string>
<string name="text_5d6bce93c0649a63" formatted="false">"最多保存 16 个自定义快捷键"</string>
<string name="text_f33cb21422f62ee8" formatted="false">"最多固定 8 个快捷键"</string>
<string name="text_4d8c1c5b42830791" formatted="false">"未知"</string>
<string name="text_6b1fa1d7159de777" formatted="false">"本地编辑,输入不会发送到远端"</string>
<string name="text_cb9eaa63c25d383e" formatted="false">"添加到常用栏"</string>
<string name="text_6135d4159e892541" formatted="false">"移除"</string>
<string name="text_e693ff5832c7f46d" formatted="false">"窗口菜单"</string>
<string name="text_096a247cc5455ba7" formatted="false">"等待远端平台信息"</string>
<string name="text_39c7740197c41d44" formatted="false">"管理与自定义"</string>
<string name="text_2dc8c27b75796b36" formatted="false">"管理快捷键"</string>
<string name="text_33517926747180e6" formatted="false">"粘贴"</string>
<string name="text_5b50d7c4b5950dc5" formatted="false">"系统"</string>
<string name="text_45123fa07e22fb3e" formatted="false">"终端复制"</string>
<string name="text_3936f3d30a763a35" formatted="false">"终端粘贴"</string>
<string name="text_051836569928a9f9" formatted="false">"编辑"</string>
<string name="text_0ecda10acc934f22" formatted="false">"编辑快捷键"</string>
<string name="text_d32d2a4e0e83d7cf" formatted="false">"聚焦搜索"</string>
<string name="text_add54b3ce4b1c661" formatted="false">"请使用系统预设中的安全选项"</string>
<string name="text_ae066f34095261c9" formatted="false">"请先选词或取消组词"</string>
<string name="text_a895bdb6f1f11e99" formatted="false">"请输入有效的快捷键名称"</string>
<string name="text_6b3213d2afed99e8" formatted="false">"请选择有效的按键"</string>
<string name="text_819569ec77acb01e" formatted="false">"运行窗口"</string>
<string name="text_22c4107f03c3533e" formatted="false">"还没有自定义快捷键"</string>
<string name="text_b07f98d4671af3f9" formatted="false">"适用远端"</string>
<string name="text_4bdabfba3368869d" formatted="false">"选择桌面方案"</string>
<string name="text_4fa28857c6f253cc" formatted="false">"选择桌面方案以加载系统预设"</string>
<string name="text_fc5f6f7462e8557a" formatted="false">"键盘上方常用栏"</string>
</resources>
@@ -315,4 +315,59 @@
<string name="text_cbacf1eafbca53e0" formatted="false">"配對資訊已複製。"</string>
<string name="text_cde42ccdeacbbbd9" formatted="false">"無法複製配對資訊,請重試。"</string>
<string name="text_7383b2ae09252c59" formatted="false">"安全儲存不可用,請解鎖裝置後重試"</string>
<string name="text_c9b9ae7a61444ab7" formatted="false">"上一頁"</string>
<string name="text_8a8542f6964852dc" formatted="false">"下一頁"</string>
<string name="text_0c4f690eb398c12e" formatted="false">"主按鍵"</string>
<string name="text_62fdb5304cf5cd9b" formatted="false">"工作管理員"</string>
<string name="text_a3030bf8f16dc63c" formatted="false">"儲存"</string>
<string name="text_ba0e2ff8201bc6a6" formatted="false">"修飾鍵"</string>
<string name="text_3a5040b68abf75f9" formatted="false">"全選"</string>
<string name="text_c2d918002afcc3d4" formatted="false">"切換應用程式"</string>
<string name="text_a7fe8e2685849c31" formatted="false">"切換視窗"</string>
<string name="text_410a8e8a6bf253ac" formatted="false">"剪下"</string>
<string name="text_6309cd49db59d165" formatted="false">"傳送組合"</string>
<string name="text_d44e9b3d3b31d37b" formatted="false">"名稱"</string>
<string name="text_6789dd11afc7c4c5" formatted="false">"向上移動"</string>
<string name="text_352c003784b1c89e" formatted="false">"固定到鍵盤上方"</string>
<string name="text_63d90d977348ab1f" formatted="false">"複製"</string>
<string name="text_ecb0d13f3f8bfd0d" formatted="false">"安全性選項"</string>
<string name="text_dd1b1da65a6c89de" formatted="false">"已有相同組合的快捷鍵"</string>
<string name="text_4563c57b5143deaa" formatted="false">"常用"</string>
<string name="text_6308bf1373bd0ee8" formatted="false">"應用程式列表"</string>
<string name="text_8dc0823d700cf875" formatted="false">"強制結束面板"</string>
<string name="text_ee2638183d3ea860" formatted="false">"快速鍵"</string>
<string name="text_7f1d9dd04cd1c7b8" formatted="false">"我的"</string>
<string name="text_7c7577d4d4fc6009" formatted="false">"按鍵"</string>
<string name="text_926a50b98ece2667" formatted="false">"復原"</string>
<string name="text_50ef2f4cf6a46924" formatted="false">"新增"</string>
<string name="text_c6904bb36f7f62c5" formatted="false">"新增快速鍵"</string>
<string name="text_5cfe4846aa8a7228" formatted="false">"顯示桌面"</string>
<string name="text_feb12adf8e0315e2" formatted="false">"更多快速鍵"</string>
<string name="text_5d6bce93c0649a63" formatted="false">"最多儲存 16 個自訂快速鍵"</string>
<string name="text_f33cb21422f62ee8" formatted="false">"最多固定 8 個快速鍵"</string>
<string name="text_4d8c1c5b42830791" formatted="false">"未知"</string>
<string name="text_6b1fa1d7159de777" formatted="false">"本機編輯,輸入不會傳送到遠端"</string>
<string name="text_cb9eaa63c25d383e" formatted="false">"加入常用列"</string>
<string name="text_6135d4159e892541" formatted="false">"移除"</string>
<string name="text_e693ff5832c7f46d" formatted="false">"視窗選單"</string>
<string name="text_096a247cc5455ba7" formatted="false">"等待遠端平台資訊"</string>
<string name="text_39c7740197c41d44" formatted="false">"管理與自訂"</string>
<string name="text_2dc8c27b75796b36" formatted="false">"管理快速鍵"</string>
<string name="text_33517926747180e6" formatted="false">"貼上"</string>
<string name="text_5b50d7c4b5950dc5" formatted="false">"系統"</string>
<string name="text_45123fa07e22fb3e" formatted="false">"終端機複製"</string>
<string name="text_3936f3d30a763a35" formatted="false">"終端機貼上"</string>
<string name="text_051836569928a9f9" formatted="false">"編輯"</string>
<string name="text_0ecda10acc934f22" formatted="false">"編輯快速鍵"</string>
<string name="text_d32d2a4e0e83d7cf" formatted="false">"Spotlight 搜尋"</string>
<string name="text_add54b3ce4b1c661" formatted="false">"請使用系統預設中的安全性選項"</string>
<string name="text_ae066f34095261c9" formatted="false">"請先選字或取消組字"</string>
<string name="text_a895bdb6f1f11e99" formatted="false">"請輸入有效的快速鍵名稱"</string>
<string name="text_6b3213d2afed99e8" formatted="false">"請選擇有效的按鍵"</string>
<string name="text_819569ec77acb01e" formatted="false">"執行視窗"</string>
<string name="text_22c4107f03c3533e" formatted="false">"尚無自訂快速鍵"</string>
<string name="text_b07f98d4671af3f9" formatted="false">"適用遠端"</string>
<string name="text_4bdabfba3368869d" formatted="false">"選擇桌面環境"</string>
<string name="text_4fa28857c6f253cc" formatted="false">"選擇桌面環境以載入系統預設"</string>
<string name="text_fc5f6f7462e8557a" formatted="false">"鍵盤上方常用列"</string>
</resources>
@@ -315,4 +315,59 @@
<string name="text_cbacf1eafbca53e0" formatted="false">"Kopplungsdaten kopiert."</string>
<string name="text_cde42ccdeacbbbd9" formatted="false">"Kopplungsdaten konnten nicht kopiert werden. Bitte erneut versuchen."</string>
<string name="text_7383b2ae09252c59" formatted="false">"Der sichere Speicher ist nicht verfügbar. Bitte entsperren Sie das Gerät und versuchen Sie es erneut"</string>
<string name="text_c9b9ae7a61444ab7" formatted="false">"Vorherige Seite"</string>
<string name="text_8a8542f6964852dc" formatted="false">"Nächste Seite"</string>
<string name="text_0c4f690eb398c12e" formatted="false">"Haupttaste"</string>
<string name="text_62fdb5304cf5cd9b" formatted="false">"Task-Manager"</string>
<string name="text_a3030bf8f16dc63c" formatted="false">"Speichern"</string>
<string name="text_ba0e2ff8201bc6a6" formatted="false">"Modifikatortasten"</string>
<string name="text_3a5040b68abf75f9" formatted="false">"Alles auswählen"</string>
<string name="text_c2d918002afcc3d4" formatted="false">"Apps wechseln"</string>
<string name="text_a7fe8e2685849c31" formatted="false">"Fenster wechseln"</string>
<string name="text_410a8e8a6bf253ac" formatted="false">"Ausschneiden"</string>
<string name="text_6309cd49db59d165" formatted="false">"Tastenkombination"</string>
<string name="text_d44e9b3d3b31d37b" formatted="false">"Name"</string>
<string name="text_6789dd11afc7c4c5" formatted="false">"Nach oben"</string>
<string name="text_352c003784b1c89e" formatted="false">"Über der Tastatur anheften"</string>
<string name="text_63d90d977348ab1f" formatted="false">"Kopieren"</string>
<string name="text_ecb0d13f3f8bfd0d" formatted="false">"Sicherheitsoptionen"</string>
<string name="text_dd1b1da65a6c89de" formatted="false">"Diese Kombination ist bereits vorhanden"</string>
<string name="text_4563c57b5143deaa" formatted="false">"Favoriten"</string>
<string name="text_6308bf1373bd0ee8" formatted="false">"App-Liste"</string>
<string name="text_8dc0823d700cf875" formatted="false">"Dialog zum sofortigen Beenden"</string>
<string name="text_ee2638183d3ea860" formatted="false">"Tastenkürzel"</string>
<string name="text_7f1d9dd04cd1c7b8" formatted="false">"Eigene"</string>
<string name="text_7c7577d4d4fc6009" formatted="false">"Tasten"</string>
<string name="text_926a50b98ece2667" formatted="false">"Rückgängig"</string>
<string name="text_50ef2f4cf6a46924" formatted="false">"Neu"</string>
<string name="text_c6904bb36f7f62c5" formatted="false">"Neues Tastenkürzel"</string>
<string name="text_5cfe4846aa8a7228" formatted="false">"Desktop anzeigen"</string>
<string name="text_feb12adf8e0315e2" formatted="false">"Weitere Tastenkürzel"</string>
<string name="text_5d6bce93c0649a63" formatted="false">"Bis zu 16 eigene Tastenkürzel speichern"</string>
<string name="text_f33cb21422f62ee8" formatted="false">"Bis zu 8 Tastenkürzel anheften"</string>
<string name="text_4d8c1c5b42830791" formatted="false">"Unbekannt"</string>
<string name="text_6b1fa1d7159de777" formatted="false">"Lokale Bearbeitung. Eingaben bleiben auf diesem Gerät."</string>
<string name="text_cb9eaa63c25d383e" formatted="false">"Zur Favoritenleiste hinzufügen"</string>
<string name="text_6135d4159e892541" formatted="false">"Entfernen"</string>
<string name="text_e693ff5832c7f46d" formatted="false">"Fenstermenü"</string>
<string name="text_096a247cc5455ba7" formatted="false">"Warten auf Informationen zur Remote-Plattform"</string>
<string name="text_39c7740197c41d44" formatted="false">"Verwalten und anpassen"</string>
<string name="text_2dc8c27b75796b36" formatted="false">"Tastenkürzel verwalten"</string>
<string name="text_33517926747180e6" formatted="false">"Einfügen"</string>
<string name="text_5b50d7c4b5950dc5" formatted="false">"System"</string>
<string name="text_45123fa07e22fb3e" formatted="false">"Im Terminal kopieren"</string>
<string name="text_3936f3d30a763a35" formatted="false">"Im Terminal einfügen"</string>
<string name="text_051836569928a9f9" formatted="false">"Bearbeiten"</string>
<string name="text_0ecda10acc934f22" formatted="false">"Tastenkürzel bearbeiten"</string>
<string name="text_d32d2a4e0e83d7cf" formatted="false">"Spotlight-Suche"</string>
<string name="text_add54b3ce4b1c661" formatted="false">"Sicherheitsoptionen in den Systemvorgaben verwenden"</string>
<string name="text_ae066f34095261c9" formatted="false">"Zuerst die aktuelle Texteingabe bestätigen oder abbrechen"</string>
<string name="text_a895bdb6f1f11e99" formatted="false">"Namen mit 1–64 Zeichen eingeben"</string>
<string name="text_6b3213d2afed99e8" formatted="false">"Eine gültige Taste auswählen"</string>
<string name="text_819569ec77acb01e" formatted="false">"Ausführen-Dialog"</string>
<string name="text_22c4107f03c3533e" formatted="false">"Noch keine eigenen Tastenkürzel"</string>
<string name="text_b07f98d4671af3f9" formatted="false">"Remote-Plattform"</string>
<string name="text_4bdabfba3368869d" formatted="false">"Desktop-Umgebung auswählen"</string>
<string name="text_4fa28857c6f253cc" formatted="false">"Desktop-Umgebung wählen, um Systemvorgaben zu laden"</string>
<string name="text_fc5f6f7462e8557a" formatted="false">"Favoriten über der Tastatur"</string>
</resources>
@@ -315,4 +315,59 @@
<string name="text_cbacf1eafbca53e0" formatted="false">"Información de emparejamiento copiada."</string>
<string name="text_cde42ccdeacbbbd9" formatted="false">"No se pudo copiar la información de emparejamiento. Inténtelo de nuevo."</string>
<string name="text_7383b2ae09252c59" formatted="false">"El almacenamiento seguro no está disponible. Desbloquee el dispositivo e inténtelo nuevamente."</string>
<string name="text_c9b9ae7a61444ab7" formatted="false">"Página anterior"</string>
<string name="text_8a8542f6964852dc" formatted="false">"Página siguiente"</string>
<string name="text_0c4f690eb398c12e" formatted="false">"Tecla principal"</string>
<string name="text_62fdb5304cf5cd9b" formatted="false">"Administrador de tareas"</string>
<string name="text_a3030bf8f16dc63c" formatted="false">"Guardar"</string>
<string name="text_ba0e2ff8201bc6a6" formatted="false">"Modificadores"</string>
<string name="text_3a5040b68abf75f9" formatted="false">"Seleccionar todo"</string>
<string name="text_c2d918002afcc3d4" formatted="false">"Cambiar de aplicación"</string>
<string name="text_a7fe8e2685849c31" formatted="false">"Cambiar de ventana"</string>
<string name="text_410a8e8a6bf253ac" formatted="false">"Cortar"</string>
<string name="text_6309cd49db59d165" formatted="false">"Combinación de teclas"</string>
<string name="text_d44e9b3d3b31d37b" formatted="false">"Nombre"</string>
<string name="text_6789dd11afc7c4c5" formatted="false">"Subir"</string>
<string name="text_352c003784b1c89e" formatted="false">"Fijar sobre el teclado"</string>
<string name="text_63d90d977348ab1f" formatted="false">"Copiar"</string>
<string name="text_ecb0d13f3f8bfd0d" formatted="false">"Opciones de seguridad"</string>
<string name="text_dd1b1da65a6c89de" formatted="false">"Esta combinación ya existe"</string>
<string name="text_4563c57b5143deaa" formatted="false">"Favoritos"</string>
<string name="text_6308bf1373bd0ee8" formatted="false">"Lista de aplicaciones"</string>
<string name="text_8dc0823d700cf875" formatted="false">"Diálogo Forzar salida"</string>
<string name="text_ee2638183d3ea860" formatted="false">"Atajos"</string>
<string name="text_7f1d9dd04cd1c7b8" formatted="false">"Mis atajos"</string>
<string name="text_7c7577d4d4fc6009" formatted="false">"Teclas"</string>
<string name="text_926a50b98ece2667" formatted="false">"Deshacer"</string>
<string name="text_50ef2f4cf6a46924" formatted="false">"Nuevo"</string>
<string name="text_c6904bb36f7f62c5" formatted="false">"Nuevo atajo"</string>
<string name="text_5cfe4846aa8a7228" formatted="false">"Mostrar escritorio"</string>
<string name="text_feb12adf8e0315e2" formatted="false">"Más atajos"</string>
<string name="text_5d6bce93c0649a63" formatted="false">"Guarda hasta 16 atajos personalizados"</string>
<string name="text_f33cb21422f62ee8" formatted="false">"Fija hasta 8 atajos"</string>
<string name="text_4d8c1c5b42830791" formatted="false">"Desconocido"</string>
<string name="text_6b1fa1d7159de777" formatted="false">"Edición local. Lo escrito permanece en este dispositivo."</string>
<string name="text_cb9eaa63c25d383e" formatted="false">"Añadir a la barra de favoritos"</string>
<string name="text_6135d4159e892541" formatted="false">"Quitar"</string>
<string name="text_e693ff5832c7f46d" formatted="false">"Menú de ventana"</string>
<string name="text_096a247cc5455ba7" formatted="false">"Esperando información del sistema remoto"</string>
<string name="text_39c7740197c41d44" formatted="false">"Gestionar y personalizar"</string>
<string name="text_2dc8c27b75796b36" formatted="false">"Gestionar atajos"</string>
<string name="text_33517926747180e6" formatted="false">"Pegar"</string>
<string name="text_5b50d7c4b5950dc5" formatted="false">"Sistema"</string>
<string name="text_45123fa07e22fb3e" formatted="false">"Copiar en terminal"</string>
<string name="text_3936f3d30a763a35" formatted="false">"Pegar en terminal"</string>
<string name="text_051836569928a9f9" formatted="false">"Editar"</string>
<string name="text_0ecda10acc934f22" formatted="false">"Editar atajo"</string>
<string name="text_d32d2a4e0e83d7cf" formatted="false">"Búsqueda de Spotlight"</string>
<string name="text_add54b3ce4b1c661" formatted="false">"Usa Opciones de seguridad en los ajustes del sistema"</string>
<string name="text_ae066f34095261c9" formatted="false">"Confirma o cancela primero la composición actual"</string>
<string name="text_a895bdb6f1f11e99" formatted="false">"Introduce un nombre de 1 a 64 caracteres"</string>
<string name="text_6b3213d2afed99e8" formatted="false">"Selecciona una tecla válida"</string>
<string name="text_819569ec77acb01e" formatted="false">"Diálogo Ejecutar"</string>
<string name="text_22c4107f03c3533e" formatted="false">"Aún no hay atajos personalizados"</string>
<string name="text_b07f98d4671af3f9" formatted="false">"Sistema remoto"</string>
<string name="text_4bdabfba3368869d" formatted="false">"Elegir entorno de escritorio"</string>
<string name="text_4fa28857c6f253cc" formatted="false">"Elige un entorno para cargar los ajustes del sistema"</string>
<string name="text_fc5f6f7462e8557a" formatted="false">"Favoritos sobre el teclado"</string>
</resources>
@@ -315,4 +315,59 @@
<string name="text_cbacf1eafbca53e0" formatted="false">"Informations d’association copiées."</string>
<string name="text_cde42ccdeacbbbd9" formatted="false">"Impossible de copier les informations d’association. Réessayez."</string>
<string name="text_7383b2ae09252c59" formatted="false">"Le stockage sécurisé n\'est pas disponible, veuillez déverrouiller l\'appareil et réessayer"</string>
<string name="text_c9b9ae7a61444ab7" formatted="false">"Page précédente"</string>
<string name="text_8a8542f6964852dc" formatted="false">"Page suivante"</string>
<string name="text_0c4f690eb398c12e" formatted="false">"Touche principale"</string>
<string name="text_62fdb5304cf5cd9b" formatted="false">"Gestionnaire des tâches"</string>
<string name="text_a3030bf8f16dc63c" formatted="false">"Enregistrer"</string>
<string name="text_ba0e2ff8201bc6a6" formatted="false">"Touches de modification"</string>
<string name="text_3a5040b68abf75f9" formatted="false">"Sélectionner tout"</string>
<string name="text_c2d918002afcc3d4" formatted="false">"Changer d’application"</string>
<string name="text_a7fe8e2685849c31" formatted="false">"Changer de fenêtre"</string>
<string name="text_410a8e8a6bf253ac" formatted="false">"Couper"</string>
<string name="text_6309cd49db59d165" formatted="false">"Combinaison à envoyer"</string>
<string name="text_d44e9b3d3b31d37b" formatted="false">"Nom"</string>
<string name="text_6789dd11afc7c4c5" formatted="false">"Monter"</string>
<string name="text_352c003784b1c89e" formatted="false">"Épingler au-dessus du clavier"</string>
<string name="text_63d90d977348ab1f" formatted="false">"Copier"</string>
<string name="text_ecb0d13f3f8bfd0d" formatted="false">"Options de sécurité"</string>
<string name="text_dd1b1da65a6c89de" formatted="false">"Cette combinaison existe déjà"</string>
<string name="text_4563c57b5143deaa" formatted="false">"Favoris"</string>
<string name="text_6308bf1373bd0ee8" formatted="false">"Liste des applications"</string>
<string name="text_8dc0823d700cf875" formatted="false">"Fenêtre Forcer à quitter"</string>
<string name="text_ee2638183d3ea860" formatted="false">"Raccourcis"</string>
<string name="text_7f1d9dd04cd1c7b8" formatted="false">"Mes raccourcis"</string>
<string name="text_7c7577d4d4fc6009" formatted="false">"Touches"</string>
<string name="text_926a50b98ece2667" formatted="false">"Annuler l’action"</string>
<string name="text_50ef2f4cf6a46924" formatted="false">"Nouveau"</string>
<string name="text_c6904bb36f7f62c5" formatted="false">"Nouveau raccourci"</string>
<string name="text_5cfe4846aa8a7228" formatted="false">"Afficher le bureau"</string>
<string name="text_feb12adf8e0315e2" formatted="false">"Autres raccourcis"</string>
<string name="text_5d6bce93c0649a63" formatted="false">"Enregistrez jusqu’à 16 raccourcis personnalisés"</string>
<string name="text_f33cb21422f62ee8" formatted="false">"Épinglez jusqu’à 8 raccourcis"</string>
<string name="text_4d8c1c5b42830791" formatted="false">"Inconnu"</string>
<string name="text_6b1fa1d7159de777" formatted="false">"Édition locale. La saisie reste sur cet appareil."</string>
<string name="text_cb9eaa63c25d383e" formatted="false">"Ajouter à la barre des favoris"</string>
<string name="text_6135d4159e892541" formatted="false">"Retirer"</string>
<string name="text_e693ff5832c7f46d" formatted="false">"Menu de la fenêtre"</string>
<string name="text_096a247cc5455ba7" formatted="false">"En attente des informations du système distant"</string>
<string name="text_39c7740197c41d44" formatted="false">"Gérer et personnaliser"</string>
<string name="text_2dc8c27b75796b36" formatted="false">"Gérer les raccourcis"</string>
<string name="text_33517926747180e6" formatted="false">"Coller"</string>
<string name="text_5b50d7c4b5950dc5" formatted="false">"Système"</string>
<string name="text_45123fa07e22fb3e" formatted="false">"Copier dans le terminal"</string>
<string name="text_3936f3d30a763a35" formatted="false">"Coller dans le terminal"</string>
<string name="text_051836569928a9f9" formatted="false">"Modifier"</string>
<string name="text_0ecda10acc934f22" formatted="false">"Modifier le raccourci"</string>
<string name="text_d32d2a4e0e83d7cf" formatted="false">"Recherche Spotlight"</string>
<string name="text_add54b3ce4b1c661" formatted="false">"Utilisez les options de sécurité des préréglages système"</string>
<string name="text_ae066f34095261c9" formatted="false">"Validez ou annulez d’abord la composition en cours"</string>
<string name="text_a895bdb6f1f11e99" formatted="false">"Saisissez un nom de 1 à 64 caractères"</string>
<string name="text_6b3213d2afed99e8" formatted="false">"Sélectionnez une touche valide"</string>
<string name="text_819569ec77acb01e" formatted="false">"Fenêtre Exécuter"</string>
<string name="text_22c4107f03c3533e" formatted="false">"Aucun raccourci personnalisé"</string>
<string name="text_b07f98d4671af3f9" formatted="false">"Système distant"</string>
<string name="text_4bdabfba3368869d" formatted="false">"Choisir l’environnement de bureau"</string>
<string name="text_4fa28857c6f253cc" formatted="false">"Choisissez un environnement pour charger les préréglages système"</string>
<string name="text_fc5f6f7462e8557a" formatted="false">"Favoris au-dessus du clavier"</string>
</resources>
@@ -315,4 +315,59 @@
<string name="text_cbacf1eafbca53e0" formatted="false">"ペアリング情報をコピーしました。"</string>
<string name="text_cde42ccdeacbbbd9" formatted="false">"ペアリング情報をコピーできません。もう一度お試しください。"</string>
<string name="text_7383b2ae09252c59" formatted="false">"安全なストレージが利用できません。デバイスのロックを解除して、もう一度お試しください。"</string>
<string name="text_c9b9ae7a61444ab7" formatted="false">"前のページ"</string>
<string name="text_8a8542f6964852dc" formatted="false">"次のページ"</string>
<string name="text_0c4f690eb398c12e" formatted="false">"メインキー"</string>
<string name="text_62fdb5304cf5cd9b" formatted="false">"タスクマネージャー"</string>
<string name="text_a3030bf8f16dc63c" formatted="false">"保存"</string>
<string name="text_ba0e2ff8201bc6a6" formatted="false">"修飾キー"</string>
<string name="text_3a5040b68abf75f9" formatted="false">"全て選択"</string>
<string name="text_c2d918002afcc3d4" formatted="false">"アプリを切り替え"</string>
<string name="text_a7fe8e2685849c31" formatted="false">"ウインドウを切り替え"</string>
<string name="text_410a8e8a6bf253ac" formatted="false">"切り取り"</string>
<string name="text_6309cd49db59d165" formatted="false">"送信するキーの組み合わせ"</string>
<string name="text_d44e9b3d3b31d37b" formatted="false">"名前"</string>
<string name="text_6789dd11afc7c4c5" formatted="false">"上へ移動"</string>
<string name="text_352c003784b1c89e" formatted="false">"キーボードの上に固定"</string>
<string name="text_63d90d977348ab1f" formatted="false">"コピー"</string>
<string name="text_ecb0d13f3f8bfd0d" formatted="false">"セキュリティオプション"</string>
<string name="text_dd1b1da65a6c89de" formatted="false">"この組み合わせは登録済みです"</string>
<string name="text_4563c57b5143deaa" formatted="false">"よく使う項目"</string>
<string name="text_6308bf1373bd0ee8" formatted="false">"アプリ一覧"</string>
<string name="text_8dc0823d700cf875" formatted="false">"強制終了ダイアログ"</string>
<string name="text_ee2638183d3ea860" formatted="false">"ショートカット"</string>
<string name="text_7f1d9dd04cd1c7b8" formatted="false">"マイ項目"</string>
<string name="text_7c7577d4d4fc6009" formatted="false">"キー"</string>
<string name="text_926a50b98ece2667" formatted="false">"取り消す"</string>
<string name="text_50ef2f4cf6a46924" formatted="false">"新規"</string>
<string name="text_c6904bb36f7f62c5" formatted="false">"ショートカットを作成"</string>
<string name="text_5cfe4846aa8a7228" formatted="false">"デスクトップを表示"</string>
<string name="text_feb12adf8e0315e2" formatted="false">"その他のショートカット"</string>
<string name="text_5d6bce93c0649a63" formatted="false">"カスタムショートカットは16個まで保存できます"</string>
<string name="text_f33cb21422f62ee8" formatted="false">"固定できるショートカットは8個までです"</string>
<string name="text_4d8c1c5b42830791" formatted="false">"不明"</string>
<string name="text_6b1fa1d7159de777" formatted="false">"ローカル編集。入力はリモートに送信されません。"</string>
<string name="text_cb9eaa63c25d383e" formatted="false">"お気に入りバーに追加"</string>
<string name="text_6135d4159e892541" formatted="false">"取り除く"</string>
<string name="text_e693ff5832c7f46d" formatted="false">"ウインドウメニュー"</string>
<string name="text_096a247cc5455ba7" formatted="false">"リモートのOS情報を待っています"</string>
<string name="text_39c7740197c41d44" formatted="false">"管理とカスタマイズ"</string>
<string name="text_2dc8c27b75796b36" formatted="false">"ショートカットを管理"</string>
<string name="text_33517926747180e6" formatted="false">"貼り付け"</string>
<string name="text_5b50d7c4b5950dc5" formatted="false">"システム"</string>
<string name="text_45123fa07e22fb3e" formatted="false">"端末でコピー"</string>
<string name="text_3936f3d30a763a35" formatted="false">"端末に貼り付け"</string>
<string name="text_051836569928a9f9" formatted="false">"編集"</string>
<string name="text_0ecda10acc934f22" formatted="false">"ショートカットを編集"</string>
<string name="text_d32d2a4e0e83d7cf" formatted="false">"Spotlight検索"</string>
<string name="text_add54b3ce4b1c661" formatted="false">"システムプリセットのセキュリティオプションを使用してください"</string>
<string name="text_ae066f34095261c9" formatted="false">"先に変換を確定またはキャンセルしてください"</string>
<string name="text_a895bdb6f1f11e99" formatted="false">"ショートカット名を1〜64文字で入力してください"</string>
<string name="text_6b3213d2afed99e8" formatted="false">"有効なキーを選択してください"</string>
<string name="text_819569ec77acb01e" formatted="false">"実行ダイアログ"</string>
<string name="text_22c4107f03c3533e" formatted="false">"カスタムショートカットはまだありません"</string>
<string name="text_b07f98d4671af3f9" formatted="false">"対象リモートOS"</string>
<string name="text_4bdabfba3368869d" formatted="false">"デスクトップ環境を選択"</string>
<string name="text_4fa28857c6f253cc" formatted="false">"デスクトップ環境を選択してプリセットを読み込みます"</string>
<string name="text_fc5f6f7462e8557a" formatted="false">"キーボード上のお気に入り"</string>
</resources>
@@ -315,4 +315,59 @@
<string name="text_cbacf1eafbca53e0" formatted="false">"페어링 정보를 복사했습니다."</string>
<string name="text_cde42ccdeacbbbd9" formatted="false">"페어링 정보를 복사할 수 없습니다. 다시 시도하세요."</string>
<string name="text_7383b2ae09252c59" formatted="false">"보안 저장소를 사용할 수 없습니다. 장치를 잠금 해제한 후 다시 시도해 주세요."</string>
<string name="text_c9b9ae7a61444ab7" formatted="false">"이전 페이지"</string>
<string name="text_8a8542f6964852dc" formatted="false">"다음 페이지"</string>
<string name="text_0c4f690eb398c12e" formatted="false">"기본 키"</string>
<string name="text_62fdb5304cf5cd9b" formatted="false">"작업 관리자"</string>
<string name="text_a3030bf8f16dc63c" formatted="false">"저장"</string>
<string name="text_ba0e2ff8201bc6a6" formatted="false">"보조 키"</string>
<string name="text_3a5040b68abf75f9" formatted="false">"모두 선택"</string>
<string name="text_c2d918002afcc3d4" formatted="false">"앱 전환"</string>
<string name="text_a7fe8e2685849c31" formatted="false">"창 전환"</string>
<string name="text_410a8e8a6bf253ac" formatted="false">"잘라내기"</string>
<string name="text_6309cd49db59d165" formatted="false">"전송할 키 조합"</string>
<string name="text_d44e9b3d3b31d37b" formatted="false">"이름"</string>
<string name="text_6789dd11afc7c4c5" formatted="false">"위로 이동"</string>
<string name="text_352c003784b1c89e" formatted="false">"키보드 위에 고정"</string>
<string name="text_63d90d977348ab1f" formatted="false">"복사"</string>
<string name="text_ecb0d13f3f8bfd0d" formatted="false">"보안 옵션"</string>
<string name="text_dd1b1da65a6c89de" formatted="false">"이미 등록된 키 조합입니다"</string>
<string name="text_4563c57b5143deaa" formatted="false">"자주 사용"</string>
<string name="text_6308bf1373bd0ee8" formatted="false">"앱 목록"</string>
<string name="text_8dc0823d700cf875" formatted="false">"강제 종료 대화상자"</string>
<string name="text_ee2638183d3ea860" formatted="false">"단축키"</string>
<string name="text_7f1d9dd04cd1c7b8" formatted="false">"내 단축키"</string>
<string name="text_7c7577d4d4fc6009" formatted="false">"키"</string>
<string name="text_926a50b98ece2667" formatted="false">"실행 취소"</string>
<string name="text_50ef2f4cf6a46924" formatted="false">"새로 만들기"</string>
<string name="text_c6904bb36f7f62c5" formatted="false">"새 단축키"</string>
<string name="text_5cfe4846aa8a7228" formatted="false">"바탕 화면 표시"</string>
<string name="text_feb12adf8e0315e2" formatted="false">"더 많은 단축키"</string>
<string name="text_5d6bce93c0649a63" formatted="false">"사용자 지정 단축키는 최대 16개까지 저장할 수 있습니다"</string>
<string name="text_f33cb21422f62ee8" formatted="false">"단축키는 최대 8개까지 고정할 수 있습니다"</string>
<string name="text_4d8c1c5b42830791" formatted="false">"알 수 없음"</string>
<string name="text_6b1fa1d7159de777" formatted="false">"로컬 편집 중입니다. 입력은 원격 기기로 전송되지 않습니다."</string>
<string name="text_cb9eaa63c25d383e" formatted="false">"즐겨찾기 모음에 추가"</string>
<string name="text_6135d4159e892541" formatted="false">"제거"</string>
<string name="text_e693ff5832c7f46d" formatted="false">"창 메뉴"</string>
<string name="text_096a247cc5455ba7" formatted="false">"원격 플랫폼 정보를 기다리는 중"</string>
<string name="text_39c7740197c41d44" formatted="false">"관리 및 사용자 지정"</string>
<string name="text_2dc8c27b75796b36" formatted="false">"단축키 관리"</string>
<string name="text_33517926747180e6" formatted="false">"붙여넣기"</string>
<string name="text_5b50d7c4b5950dc5" formatted="false">"시스템"</string>
<string name="text_45123fa07e22fb3e" formatted="false">"터미널 복사"</string>
<string name="text_3936f3d30a763a35" formatted="false">"터미널 붙여넣기"</string>
<string name="text_051836569928a9f9" formatted="false">"편집"</string>
<string name="text_0ecda10acc934f22" formatted="false">"단축키 편집"</string>
<string name="text_d32d2a4e0e83d7cf" formatted="false">"Spotlight 검색"</string>
<string name="text_add54b3ce4b1c661" formatted="false">"시스템 프리셋의 보안 옵션을 사용하세요"</string>
<string name="text_ae066f34095261c9" formatted="false">"먼저 조합 중인 문자를 확정하거나 취소하세요"</string>
<string name="text_a895bdb6f1f11e99" formatted="false">"단축키 이름을 1~64자로 입력하세요"</string>
<string name="text_6b3213d2afed99e8" formatted="false">"유효한 키를 선택하세요"</string>
<string name="text_819569ec77acb01e" formatted="false">"실행 대화상자"</string>
<string name="text_22c4107f03c3533e" formatted="false">"아직 사용자 지정 단축키가 없습니다"</string>
<string name="text_b07f98d4671af3f9" formatted="false">"대상 원격 플랫폼"</string>
<string name="text_4bdabfba3368869d" formatted="false">"데스크톱 환경 선택"</string>
<string name="text_4fa28857c6f253cc" formatted="false">"데스크톱 환경을 선택하여 시스템 프리셋을 불러오세요"</string>
<string name="text_fc5f6f7462e8557a" formatted="false">"키보드 위 즐겨찾기 모음"</string>
</resources>
@@ -315,4 +315,59 @@
<string name="text_cbacf1eafbca53e0" formatted="false">"Informações de pareamento copiadas."</string>
<string name="text_cde42ccdeacbbbd9" formatted="false">"Não foi possível copiar as informações de pareamento. Tente novamente."</string>
<string name="text_7383b2ae09252c59" formatted="false">"O armazenamento seguro não está disponível. Desbloqueie o dispositivo e tente novamente"</string>
<string name="text_c9b9ae7a61444ab7" formatted="false">"Página anterior"</string>
<string name="text_8a8542f6964852dc" formatted="false">"Próxima página"</string>
<string name="text_0c4f690eb398c12e" formatted="false">"Tecla principal"</string>
<string name="text_62fdb5304cf5cd9b" formatted="false">"Gerenciador de Tarefas"</string>
<string name="text_a3030bf8f16dc63c" formatted="false">"Salvar"</string>
<string name="text_ba0e2ff8201bc6a6" formatted="false">"Modificadores"</string>
<string name="text_3a5040b68abf75f9" formatted="false">"Selecionar tudo"</string>
<string name="text_c2d918002afcc3d4" formatted="false">"Alternar aplicativos"</string>
<string name="text_a7fe8e2685849c31" formatted="false">"Alternar janelas"</string>
<string name="text_410a8e8a6bf253ac" formatted="false">"Recortar"</string>
<string name="text_6309cd49db59d165" formatted="false">"Combinação de teclas"</string>
<string name="text_d44e9b3d3b31d37b" formatted="false">"Nome"</string>
<string name="text_6789dd11afc7c4c5" formatted="false">"Mover para cima"</string>
<string name="text_352c003784b1c89e" formatted="false">"Fixar acima do teclado"</string>
<string name="text_63d90d977348ab1f" formatted="false">"Copiar"</string>
<string name="text_ecb0d13f3f8bfd0d" formatted="false">"Opções de segurança"</string>
<string name="text_dd1b1da65a6c89de" formatted="false">"Esta combinação já existe"</string>
<string name="text_4563c57b5143deaa" formatted="false">"Favoritos"</string>
<string name="text_6308bf1373bd0ee8" formatted="false">"Lista de aplicativos"</string>
<string name="text_8dc0823d700cf875" formatted="false">"Janela Forçar Encerrar"</string>
<string name="text_ee2638183d3ea860" formatted="false">"Atalhos"</string>
<string name="text_7f1d9dd04cd1c7b8" formatted="false">"Meus atalhos"</string>
<string name="text_7c7577d4d4fc6009" formatted="false">"Teclas"</string>
<string name="text_926a50b98ece2667" formatted="false">"Desfazer"</string>
<string name="text_50ef2f4cf6a46924" formatted="false">"Novo"</string>
<string name="text_c6904bb36f7f62c5" formatted="false">"Novo atalho"</string>
<string name="text_5cfe4846aa8a7228" formatted="false">"Mostrar área de trabalho"</string>
<string name="text_feb12adf8e0315e2" formatted="false">"Mais atalhos"</string>
<string name="text_5d6bce93c0649a63" formatted="false">"Salve até 16 atalhos personalizados"</string>
<string name="text_f33cb21422f62ee8" formatted="false">"Fixe até 8 atalhos"</string>
<string name="text_4d8c1c5b42830791" formatted="false">"Desconhecido"</string>
<string name="text_6b1fa1d7159de777" formatted="false">"Edição local. A entrada fica neste dispositivo."</string>
<string name="text_cb9eaa63c25d383e" formatted="false">"Adicionar à barra de favoritos"</string>
<string name="text_6135d4159e892541" formatted="false">"Remover"</string>
<string name="text_e693ff5832c7f46d" formatted="false">"Menu da janela"</string>
<string name="text_096a247cc5455ba7" formatted="false">"Aguardando informações do sistema remoto"</string>
<string name="text_39c7740197c41d44" formatted="false">"Gerenciar e personalizar"</string>
<string name="text_2dc8c27b75796b36" formatted="false">"Gerenciar atalhos"</string>
<string name="text_33517926747180e6" formatted="false">"Colar"</string>
<string name="text_5b50d7c4b5950dc5" formatted="false">"Sistema"</string>
<string name="text_45123fa07e22fb3e" formatted="false">"Copiar no terminal"</string>
<string name="text_3936f3d30a763a35" formatted="false">"Colar no terminal"</string>
<string name="text_051836569928a9f9" formatted="false">"Editar"</string>
<string name="text_0ecda10acc934f22" formatted="false">"Editar atalho"</string>
<string name="text_d32d2a4e0e83d7cf" formatted="false">"Busca do Spotlight"</string>
<string name="text_add54b3ce4b1c661" formatted="false">"Use Opções de segurança nas predefinições do sistema"</string>
<string name="text_ae066f34095261c9" formatted="false">"Confirme ou cancele primeiro a composição atual"</string>
<string name="text_a895bdb6f1f11e99" formatted="false">"Insira um nome de 1 a 64 caracteres"</string>
<string name="text_6b3213d2afed99e8" formatted="false">"Selecione uma tecla válida"</string>
<string name="text_819569ec77acb01e" formatted="false">"Janela Executar"</string>
<string name="text_22c4107f03c3533e" formatted="false">"Ainda não há atalhos personalizados"</string>
<string name="text_b07f98d4671af3f9" formatted="false">"Sistema remoto"</string>
<string name="text_4bdabfba3368869d" formatted="false">"Escolher ambiente de trabalho"</string>
<string name="text_4fa28857c6f253cc" formatted="false">"Escolha um ambiente para carregar as predefinições do sistema"</string>
<string name="text_fc5f6f7462e8557a" formatted="false">"Favoritos acima do teclado"</string>
</resources>
@@ -315,4 +315,59 @@
<string name="text_cbacf1eafbca53e0" formatted="false">"Данные сопряжения скопированы."</string>
<string name="text_cde42ccdeacbbbd9" formatted="false">"Не удалось скопировать данные сопряжения. Повторите попытку."</string>
<string name="text_7383b2ae09252c59" formatted="false">"Безопасное хранилище недоступно. Разблокируйте устройство и повторите попытку."</string>
<string name="text_c9b9ae7a61444ab7" formatted="false">"Предыдущая страница"</string>
<string name="text_8a8542f6964852dc" formatted="false">"Следующая страница"</string>
<string name="text_0c4f690eb398c12e" formatted="false">"Основная клавиша"</string>
<string name="text_62fdb5304cf5cd9b" formatted="false">"Диспетчер задач"</string>
<string name="text_a3030bf8f16dc63c" formatted="false">"Сохранить"</string>
<string name="text_ba0e2ff8201bc6a6" formatted="false">"Клавиши-модификаторы"</string>
<string name="text_3a5040b68abf75f9" formatted="false">"Выбрать все"</string>
<string name="text_c2d918002afcc3d4" formatted="false">"Переключить приложение"</string>
<string name="text_a7fe8e2685849c31" formatted="false">"Переключить окно"</string>
<string name="text_410a8e8a6bf253ac" formatted="false">"Вырезать"</string>
<string name="text_6309cd49db59d165" formatted="false">"Сочетание клавиш"</string>
<string name="text_d44e9b3d3b31d37b" formatted="false">"Название"</string>
<string name="text_6789dd11afc7c4c5" formatted="false">"Переместить вверх"</string>
<string name="text_352c003784b1c89e" formatted="false">"Закрепить над клавиатурой"</string>
<string name="text_63d90d977348ab1f" formatted="false">"Копировать"</string>
<string name="text_ecb0d13f3f8bfd0d" formatted="false">"Параметры безопасности"</string>
<string name="text_dd1b1da65a6c89de" formatted="false">"Такое сочетание уже существует"</string>
<string name="text_4563c57b5143deaa" formatted="false">"Избранное"</string>
<string name="text_6308bf1373bd0ee8" formatted="false">"Список приложений"</string>
<string name="text_8dc0823d700cf875" formatted="false">"Окно принудительного завершения"</string>
<string name="text_ee2638183d3ea860" formatted="false">"Сочетания клавиш"</string>
<string name="text_7f1d9dd04cd1c7b8" formatted="false">"Мои"</string>
<string name="text_7c7577d4d4fc6009" formatted="false">"Клавиши"</string>
<string name="text_926a50b98ece2667" formatted="false">"Отменить"</string>
<string name="text_50ef2f4cf6a46924" formatted="false">"Создать"</string>
<string name="text_c6904bb36f7f62c5" formatted="false">"Новое сочетание"</string>
<string name="text_5cfe4846aa8a7228" formatted="false">"Показать рабочий стол"</string>
<string name="text_feb12adf8e0315e2" formatted="false">"Другие сочетания"</string>
<string name="text_5d6bce93c0649a63" formatted="false">"Можно сохранить до 16 своих сочетаний"</string>
<string name="text_f33cb21422f62ee8" formatted="false">"Можно закрепить до 8 сочетаний"</string>
<string name="text_4d8c1c5b42830791" formatted="false">"Неизвестно"</string>
<string name="text_6b1fa1d7159de777" formatted="false">"Локальное редактирование. Ввод не отправляется на удалённое устройство."</string>
<string name="text_cb9eaa63c25d383e" formatted="false">"Добавить на панель избранного"</string>
<string name="text_6135d4159e892541" formatted="false">"Убрать"</string>
<string name="text_e693ff5832c7f46d" formatted="false">"Меню окна"</string>
<string name="text_096a247cc5455ba7" formatted="false">"Ожидание сведений об удалённой системе"</string>
<string name="text_39c7740197c41d44" formatted="false">"Управление и настройка"</string>
<string name="text_2dc8c27b75796b36" formatted="false">"Управление сочетаниями"</string>
<string name="text_33517926747180e6" formatted="false">"Вставить"</string>
<string name="text_5b50d7c4b5950dc5" formatted="false">"Система"</string>
<string name="text_45123fa07e22fb3e" formatted="false">"Копировать в терминале"</string>
<string name="text_3936f3d30a763a35" formatted="false">"Вставить в терминале"</string>
<string name="text_051836569928a9f9" formatted="false">"Изменить"</string>
<string name="text_0ecda10acc934f22" formatted="false">"Изменить сочетание"</string>
<string name="text_d32d2a4e0e83d7cf" formatted="false">"Поиск Spotlight"</string>
<string name="text_add54b3ce4b1c661" formatted="false">"Используйте параметры безопасности из системных наборов"</string>
<string name="text_ae066f34095261c9" formatted="false">"Сначала подтвердите или отмените текущий ввод"</string>
<string name="text_a895bdb6f1f11e99" formatted="false">"Введите название от 1 до 64 символов"</string>
<string name="text_6b3213d2afed99e8" formatted="false">"Выберите допустимую клавишу"</string>
<string name="text_819569ec77acb01e" formatted="false">"Окно запуска"</string>
<string name="text_22c4107f03c3533e" formatted="false">"Своих сочетаний пока нет"</string>
<string name="text_b07f98d4671af3f9" formatted="false">"Удалённая система"</string>
<string name="text_4bdabfba3368869d" formatted="false">"Выберите окружение рабочего стола"</string>
<string name="text_4fa28857c6f253cc" formatted="false">"Выберите окружение, чтобы загрузить системные наборы"</string>
<string name="text_fc5f6f7462e8557a" formatted="false">"Избранное над клавиатурой"</string>
</resources>
@@ -315,4 +315,59 @@
<string name="text_cbacf1eafbca53e0" formatted="false">"Pairing information copied."</string>
<string name="text_cde42ccdeacbbbd9" formatted="false">"Unable to copy pairing information. Please try again."</string>
<string name="text_7383b2ae09252c59" formatted="false">"Secure storage is unavailable, please unlock the device and try again"</string>
<string name="text_c9b9ae7a61444ab7" formatted="false">"Previous page"</string>
<string name="text_8a8542f6964852dc" formatted="false">"Next page"</string>
<string name="text_0c4f690eb398c12e" formatted="false">"Main key"</string>
<string name="text_62fdb5304cf5cd9b" formatted="false">"Task Manager"</string>
<string name="text_a3030bf8f16dc63c" formatted="false">"Save"</string>
<string name="text_ba0e2ff8201bc6a6" formatted="false">"Modifiers"</string>
<string name="text_3a5040b68abf75f9" formatted="false">"Select all"</string>
<string name="text_c2d918002afcc3d4" formatted="false">"Switch apps"</string>
<string name="text_a7fe8e2685849c31" formatted="false">"Switch windows"</string>
<string name="text_410a8e8a6bf253ac" formatted="false">"Cut"</string>
<string name="text_6309cd49db59d165" formatted="false">"Key combination"</string>
<string name="text_d44e9b3d3b31d37b" formatted="false">"Name"</string>
<string name="text_6789dd11afc7c4c5" formatted="false">"Move up"</string>
<string name="text_352c003784b1c89e" formatted="false">"Pin above keyboard"</string>
<string name="text_63d90d977348ab1f" formatted="false">"Copy"</string>
<string name="text_ecb0d13f3f8bfd0d" formatted="false">"Security options"</string>
<string name="text_dd1b1da65a6c89de" formatted="false">"This combination already exists"</string>
<string name="text_4563c57b5143deaa" formatted="false">"Favorites"</string>
<string name="text_6308bf1373bd0ee8" formatted="false">"App list"</string>
<string name="text_8dc0823d700cf875" formatted="false">"Force Quit dialog"</string>
<string name="text_ee2638183d3ea860" formatted="false">"Shortcuts"</string>
<string name="text_7f1d9dd04cd1c7b8" formatted="false">"Mine"</string>
<string name="text_7c7577d4d4fc6009" formatted="false">"Keys"</string>
<string name="text_926a50b98ece2667" formatted="false">"Undo"</string>
<string name="text_50ef2f4cf6a46924" formatted="false">"New"</string>
<string name="text_c6904bb36f7f62c5" formatted="false">"New shortcut"</string>
<string name="text_5cfe4846aa8a7228" formatted="false">"Show desktop"</string>
<string name="text_feb12adf8e0315e2" formatted="false">"More shortcuts"</string>
<string name="text_5d6bce93c0649a63" formatted="false">"Save up to 16 custom shortcuts"</string>
<string name="text_f33cb21422f62ee8" formatted="false">"Pin up to 8 shortcuts"</string>
<string name="text_4d8c1c5b42830791" formatted="false">"Unknown"</string>
<string name="text_6b1fa1d7159de777" formatted="false">"Local editing. Input stays on this device."</string>
<string name="text_cb9eaa63c25d383e" formatted="false">"Add to favorites bar"</string>
<string name="text_6135d4159e892541" formatted="false">"Remove"</string>
<string name="text_e693ff5832c7f46d" formatted="false">"Window menu"</string>
<string name="text_096a247cc5455ba7" formatted="false">"Waiting for remote platform information"</string>
<string name="text_39c7740197c41d44" formatted="false">"Manage &amp; customize"</string>
<string name="text_2dc8c27b75796b36" formatted="false">"Manage shortcuts"</string>
<string name="text_33517926747180e6" formatted="false">"Paste"</string>
<string name="text_5b50d7c4b5950dc5" formatted="false">"System"</string>
<string name="text_45123fa07e22fb3e" formatted="false">"Terminal copy"</string>
<string name="text_3936f3d30a763a35" formatted="false">"Terminal paste"</string>
<string name="text_051836569928a9f9" formatted="false">"Edit"</string>
<string name="text_0ecda10acc934f22" formatted="false">"Edit shortcut"</string>
<string name="text_d32d2a4e0e83d7cf" formatted="false">"Spotlight search"</string>
<string name="text_add54b3ce4b1c661" formatted="false">"Use Security options in the system presets"</string>
<string name="text_ae066f34095261c9" formatted="false">"Confirm or cancel the current composition first"</string>
<string name="text_a895bdb6f1f11e99" formatted="false">"Enter a shortcut name (1–64 characters)"</string>
<string name="text_6b3213d2afed99e8" formatted="false">"Select a valid key"</string>
<string name="text_819569ec77acb01e" formatted="false">"Run dialog"</string>
<string name="text_22c4107f03c3533e" formatted="false">"No custom shortcuts yet"</string>
<string name="text_b07f98d4671af3f9" formatted="false">"Remote platform"</string>
<string name="text_4bdabfba3368869d" formatted="false">"Choose desktop environment"</string>
<string name="text_4fa28857c6f253cc" formatted="false">"Choose a desktop environment to load system presets"</string>
<string name="text_fc5f6f7462e8557a" formatted="false">"Favorites above keyboard"</string>
</resources>