added java projects for softkeyboard
8
src/java/KP2ASoftKeyboard/.classpath
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
33
src/java/KP2ASoftKeyboard/.project
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>KP2ASoftKeyboard</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding//src/keepass2android/softkeyboard/KP2AKeyboard.java=UTF-8
|
21
src/java/KP2ASoftKeyboard/AndroidManifest.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="keepass2android.softkeyboard">
|
||||
<uses-sdk android:targetSdkVersion="14" android:minSdkVersion="11"/>
|
||||
<supports-screens
|
||||
android:anyDensity="true"
|
||||
android:largeScreens="true"
|
||||
android:normalScreens="true"
|
||||
android:smallScreens="true" />
|
||||
<application android:label="@string/ime_name">
|
||||
<service android:name="KP2AKeyboard"
|
||||
android:permission="android.permission.BIND_INPUT_METHOD">
|
||||
<intent-filter>
|
||||
<action android:name="android.view.InputMethod" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="android.view.im" android:resource="@xml/method" />
|
||||
</service>
|
||||
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
4
src/java/KP2ASoftKeyboard/lint.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<lint>
|
||||
<issue id="WrongCall" severity="ignore" />
|
||||
</lint>
|
14
src/java/KP2ASoftKeyboard/project.properties
Normal file
@ -0,0 +1,14 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system edit
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
#
|
||||
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||
|
||||
# Project target.
|
||||
target=android-14
|
After Width: | Height: | Size: 885 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 536 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 859 B |
After Width: | Height: | Size: 465 B |
After Width: | Height: | Size: 771 B |
After Width: | Height: | Size: 337 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 436 B |
27
src/java/KP2ASoftKeyboard/res/layout/input.xml
Normal file
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
**
|
||||
** Copyright 2008, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<keepass2android.softkeyboard.LatinKeyboardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/keyboard"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
23
src/java/KP2ASoftKeyboard/res/values-land/dimens.xml
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
**
|
||||
** Copyright 2008, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<dimen name="key_height">46dip</dimen>
|
||||
</resources>
|
25
src/java/KP2ASoftKeyboard/res/values/colors.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
**
|
||||
** Copyright 2008, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
<resources>
|
||||
<color name="candidate_normal">#FF000000</color>
|
||||
<color name="candidate_recommended">#FFE35900</color>
|
||||
<color name="candidate_other">#ff808080</color>
|
||||
<color name="candidate_background">#bbffffff</color>
|
||||
</resources>
|
25
src/java/KP2ASoftKeyboard/res/values/dimens.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
**
|
||||
** Copyright 2008, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<dimen name="key_height">50dip</dimen>
|
||||
<dimen name="candidate_font_height">16sp</dimen>
|
||||
<dimen name="candidate_vertical_padding">6sp</dimen>
|
||||
</resources>
|
34
src/java/KP2ASoftKeyboard/res/values/strings.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
**
|
||||
** Copyright 2008, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- Title for Latin keyboard -->
|
||||
<string name="ime_name">Keepass2Android</string>
|
||||
|
||||
<!-- Symbols that are commonly considered word separators in this language -->
|
||||
<string name="word_separators">\u0020.,;:!?\n()[]*&@{}/<>_+=|"</string>
|
||||
|
||||
<!-- Labels on soft keys -->
|
||||
<string name="label_go_key">Go</string>
|
||||
<string name="label_next_key">Next</string>
|
||||
<string name="label_send_key">Send</string>
|
||||
|
||||
<!-- Labels for subtype -->
|
||||
<string name="label_subtype_generic">%s</string>
|
||||
</resources>
|
25
src/java/KP2ASoftKeyboard/res/xml/method.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/**
|
||||
* Copyright (c) 2008, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<!-- The attributes in this XML file provide configuration information -->
|
||||
<!-- for the Search Manager. -->
|
||||
|
||||
<input-method xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</input-method>
|
82
src/java/KP2ASoftKeyboard/res/xml/qwerty.xml
Normal file
@ -0,0 +1,82 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
**
|
||||
** Copyright 2008, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:keyWidth="10%p"
|
||||
android:horizontalGap="0px"
|
||||
android:verticalGap="0px"
|
||||
android:keyHeight="@dimen/key_height"
|
||||
>
|
||||
|
||||
<Row>
|
||||
<Key android:codes="113" android:keyLabel="q" android:keyEdgeFlags="left"/>
|
||||
<Key android:codes="119" android:keyLabel="w"/>
|
||||
<Key android:codes="101" android:keyLabel="e"/>
|
||||
<Key android:codes="114" android:keyLabel="r"/>
|
||||
<Key android:codes="116" android:keyLabel="t"/>
|
||||
<Key android:codes="121" android:keyLabel="y"/>
|
||||
<Key android:codes="117" android:keyLabel="u"/>
|
||||
<Key android:codes="105" android:keyLabel="i"/>
|
||||
<Key android:codes="111" android:keyLabel="o"/>
|
||||
<Key android:codes="112" android:keyLabel="p" android:keyEdgeFlags="right"/>
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
<Key android:codes="97" android:keyLabel="a" android:horizontalGap="5%p"
|
||||
android:keyEdgeFlags="left"/>
|
||||
<Key android:codes="115" android:keyLabel="s"/>
|
||||
<Key android:codes="100" android:keyLabel="d"/>
|
||||
<Key android:codes="102" android:keyLabel="f"/>
|
||||
<Key android:codes="103" android:keyLabel="g"/>
|
||||
<Key android:codes="104" android:keyLabel="h"/>
|
||||
<Key android:codes="106" android:keyLabel="j"/>
|
||||
<Key android:codes="107" android:keyLabel="k"/>
|
||||
<Key android:codes="108" android:keyLabel="l" android:keyEdgeFlags="right"/>
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
<Key android:codes="-1" android:keyIcon="@drawable/sym_keyboard_shift"
|
||||
android:keyWidth="15%p" android:isModifier="true"
|
||||
android:isSticky="true" android:keyEdgeFlags="left"/>
|
||||
<Key android:codes="122" android:keyLabel="z"/>
|
||||
<Key android:codes="120" android:keyLabel="x"/>
|
||||
<Key android:codes="99" android:keyLabel="c"/>
|
||||
<Key android:codes="118" android:keyLabel="v"/>
|
||||
<Key android:codes="98" android:keyLabel="b"/>
|
||||
<Key android:codes="110" android:keyLabel="n"/>
|
||||
<Key android:codes="109" android:keyLabel="m"/>
|
||||
<Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
|
||||
android:keyWidth="15%p" android:keyEdgeFlags="right"
|
||||
android:isRepeatable="true"/>
|
||||
</Row>
|
||||
|
||||
<Row android:rowEdgeFlags="bottom">
|
||||
<Key android:codes="-101" android:keyIcon="@drawable/sym_keyboard_done"
|
||||
android:keyWidth="20%p" android:keyEdgeFlags="left"/>
|
||||
<Key android:codes="-2" android:keyLabel="123" android:keyWidth="15%p"/>
|
||||
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
|
||||
android:keyWidth="30%p" android:isRepeatable="true"/>
|
||||
<Key android:codes="46,44" android:keyLabel=". ,"
|
||||
android:keyWidth="15%p"/>
|
||||
<Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
|
||||
android:keyWidth="20%p" android:keyEdgeFlags="right"/>
|
||||
</Row>
|
||||
</Keyboard>
|
||||
|
81
src/java/KP2ASoftKeyboard/res/xml/symbols.xml
Normal file
@ -0,0 +1,81 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
**
|
||||
** Copyright 2008, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:keyWidth="10%p"
|
||||
android:horizontalGap="0px"
|
||||
android:verticalGap="0px"
|
||||
android:keyHeight="@dimen/key_height"
|
||||
>
|
||||
|
||||
<Row>
|
||||
<Key android:codes="49" android:keyLabel="1" android:keyEdgeFlags="left"/>
|
||||
<Key android:codes="50" android:keyLabel="2"/>
|
||||
<Key android:codes="51" android:keyLabel="3"/>
|
||||
<Key android:codes="52" android:keyLabel="4"/>
|
||||
<Key android:codes="53" android:keyLabel="5"/>
|
||||
<Key android:codes="54" android:keyLabel="6"/>
|
||||
<Key android:codes="55" android:keyLabel="7"/>
|
||||
<Key android:codes="56" android:keyLabel="8"/>
|
||||
<Key android:codes="57" android:keyLabel="9"/>
|
||||
<Key android:codes="48" android:keyLabel="0" android:keyEdgeFlags="right"/>
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
<Key android:codes="64" android:keyLabel="\@" android:keyEdgeFlags="left"/>
|
||||
<Key android:codes="35" android:keyLabel="\#"/>
|
||||
<Key android:codes="36" android:keyLabel="$"/>
|
||||
<Key android:codes="37" android:keyLabel="%"/>
|
||||
<Key android:codes="38" android:keyLabel="&"/>
|
||||
<Key android:codes="42" android:keyLabel="*"/>
|
||||
<Key android:codes="45" android:keyLabel="-"/>
|
||||
<Key android:codes="61" android:keyLabel="="/>
|
||||
<Key android:codes="40" android:keyLabel="("/>
|
||||
<Key android:codes="41" android:keyLabel=")" android:keyEdgeFlags="right"/>
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
<Key android:codes="-1" android:keyIcon="@drawable/sym_keyboard_shift"
|
||||
android:keyWidth="15%p" android:isModifier="true"
|
||||
android:isSticky="true" android:keyEdgeFlags="left"/>
|
||||
<Key android:codes="33" android:keyLabel="!" />
|
||||
<Key android:codes="34" android:keyLabel="""/>
|
||||
<Key android:codes="39" android:keyLabel="\'"/>
|
||||
<Key android:codes="58" android:keyLabel=":"/>
|
||||
<Key android:codes="59" android:keyLabel=";"/>
|
||||
<Key android:codes="47" android:keyLabel="/" />
|
||||
<Key android:codes="63" android:keyLabel="\?"/>
|
||||
<Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
|
||||
android:keyWidth="15%p" android:keyEdgeFlags="right"
|
||||
android:isRepeatable="true"/>
|
||||
</Row>
|
||||
|
||||
<Row android:rowEdgeFlags="bottom">
|
||||
<Key android:codes="-3" android:keyIcon="@drawable/sym_keyboard_done"
|
||||
android:keyWidth="20%p" android:keyEdgeFlags="left" />
|
||||
<Key android:codes="-2" android:keyLabel="ABC" android:keyWidth="15%p" />
|
||||
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space" android:keyWidth="30%p"
|
||||
android:isRepeatable="true"/>
|
||||
<Key android:codes="44" android:keyLabel="," android:keyWidth="15%p" />
|
||||
<Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
|
||||
android:keyWidth="20%p" android:keyEdgeFlags="right"
|
||||
/>
|
||||
</Row>
|
||||
</Keyboard>
|
80
src/java/KP2ASoftKeyboard/res/xml/symbols_shift.xml
Normal file
@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
**
|
||||
** Copyright 2008, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:keyWidth="10%p"
|
||||
android:horizontalGap="0px"
|
||||
android:verticalGap="0px"
|
||||
android:keyHeight="@dimen/key_height"
|
||||
>
|
||||
|
||||
<Row>
|
||||
<Key android:codes="126" android:keyLabel="~" android:keyEdgeFlags="left"/>
|
||||
<Key android:codes="177" android:keyLabel="±"/>
|
||||
<Key android:codes="215" android:keyLabel="×"/>
|
||||
<Key android:codes="247" android:keyLabel="÷"/>
|
||||
<Key android:codes="8226" android:keyLabel="•"/>
|
||||
<Key android:codes="176" android:keyLabel="°"/>
|
||||
<Key android:codes="96" android:keyLabel="`"/>
|
||||
<Key android:codes="180" android:keyLabel="´"/>
|
||||
<Key android:codes="123" android:keyLabel="{"/>
|
||||
<Key android:codes="125" android:keyLabel="}" android:keyEdgeFlags="right"/>
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
<Key android:codes="169" android:keyLabel="©" android:keyEdgeFlags="left"/>
|
||||
<Key android:codes="163" android:keyLabel="£"/>
|
||||
<Key android:codes="8364" android:keyLabel="€"/>
|
||||
<Key android:codes="94" android:keyLabel="^"/>
|
||||
<Key android:codes="174" android:keyLabel="®"/>
|
||||
<Key android:codes="165" android:keyLabel="¥"/>
|
||||
<Key android:codes="95" android:keyLabel="_"/>
|
||||
<Key android:codes="43" android:keyLabel="+"/>
|
||||
<Key android:codes="91" android:keyLabel="["/>
|
||||
<Key android:codes="93" android:keyLabel="]" android:keyEdgeFlags="right"/>
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
<Key android:codes="-1" android:keyIcon="@drawable/sym_keyboard_shift"
|
||||
android:keyWidth="15%p" android:isModifier="true"
|
||||
android:isSticky="true" android:keyEdgeFlags="left"/>
|
||||
<Key android:codes="161" android:keyLabel="¡" />
|
||||
<Key android:codes="60" android:keyLabel="<"/>
|
||||
<Key android:codes="62" android:keyLabel=">"/>
|
||||
<Key android:codes="162" android:keyLabel="¢"/>
|
||||
<Key android:codes="124" android:keyLabel="|"/>
|
||||
<Key android:codes="92" android:keyLabel="\\" />
|
||||
<Key android:codes="191" android:keyLabel="¿"/>
|
||||
<Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
|
||||
android:keyWidth="15%p" android:keyEdgeFlags="right"
|
||||
android:isRepeatable="true"/>
|
||||
</Row>
|
||||
|
||||
<Row android:rowEdgeFlags="bottom">
|
||||
<Key android:codes="-3" android:keyIcon="@drawable/sym_keyboard_done"
|
||||
android:keyWidth="20%p" android:keyEdgeFlags="left" />
|
||||
<Key android:codes="-2" android:keyLabel="ABC" android:keyWidth="15%p" />
|
||||
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space" android:keyWidth="30%p"
|
||||
android:isRepeatable="true"/>
|
||||
<Key android:codes="8230" android:keyLabel="…" android:keyWidth="15%p" />
|
||||
<Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
|
||||
android:keyWidth="20%p" android:keyEdgeFlags="right" />
|
||||
</Row>
|
||||
</Keyboard>
|
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is a part of the inputmethod-common static Java library.
|
||||
* The original source code can be found at frameworks/opt/inputmethodcommon of Android Open Source
|
||||
* Project.
|
||||
*/
|
||||
|
||||
package com.android.inputmethodcommon;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceFragment;
|
||||
|
||||
/**
|
||||
* This is a helper class for an IME's settings preference fragment. It's recommended for every
|
||||
* IME to have its own settings preference fragment which inherits this class.
|
||||
*/
|
||||
public abstract class InputMethodSettingsFragment extends PreferenceFragment
|
||||
implements InputMethodSettingsInterface {
|
||||
private final InputMethodSettingsImpl mSettings = new InputMethodSettingsImpl();
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
final Context context = getActivity();
|
||||
setPreferenceScreen(getPreferenceManager().createPreferenceScreen(context));
|
||||
mSettings.init(context, getPreferenceScreen());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setInputMethodSettingsCategoryTitle(int resId) {
|
||||
mSettings.setInputMethodSettingsCategoryTitle(resId);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setInputMethodSettingsCategoryTitle(CharSequence title) {
|
||||
mSettings.setInputMethodSettingsCategoryTitle(title);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setSubtypeEnablerTitle(int resId) {
|
||||
mSettings.setSubtypeEnablerTitle(resId);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setSubtypeEnablerTitle(CharSequence title) {
|
||||
mSettings.setSubtypeEnablerTitle(title);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setSubtypeEnablerIcon(int resId) {
|
||||
mSettings.setSubtypeEnablerIcon(resId);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setSubtypeEnablerIcon(Drawable drawable) {
|
||||
mSettings.setSubtypeEnablerIcon(drawable);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mSettings.updateSubtypeEnabler();
|
||||
}
|
||||
}
|
@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is a part of the inputmethod-common static Java library.
|
||||
* The original source code can be found at frameworks/opt/inputmethodcommon of Android Open Source
|
||||
* Project.
|
||||
*/
|
||||
|
||||
package com.android.inputmethodcommon;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.preference.Preference;
|
||||
import android.preference.Preference.OnPreferenceClickListener;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.view.inputmethod.InputMethodInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/* package private */ class InputMethodSettingsImpl implements InputMethodSettingsInterface {
|
||||
private Preference mSubtypeEnablerPreference;
|
||||
private int mInputMethodSettingsCategoryTitleRes;
|
||||
private CharSequence mInputMethodSettingsCategoryTitle;
|
||||
private int mSubtypeEnablerTitleRes;
|
||||
private CharSequence mSubtypeEnablerTitle;
|
||||
private int mSubtypeEnablerIconRes;
|
||||
private Drawable mSubtypeEnablerIcon;
|
||||
private InputMethodManager mImm;
|
||||
private InputMethodInfo mImi;
|
||||
private Context mContext;
|
||||
|
||||
/**
|
||||
* Initialize internal states of this object.
|
||||
* @param context the context for this application.
|
||||
* @param prefScreen a PreferenceScreen of PreferenceActivity or PreferenceFragment.
|
||||
* @return true if this application is an IME and has two or more subtypes, false otherwise.
|
||||
*/
|
||||
public boolean init(final Context context, final PreferenceScreen prefScreen) {
|
||||
mContext = context;
|
||||
mImm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
mImi = getMyImi(context, mImm);
|
||||
if (mImi == null || mImi.getSubtypeCount() <= 1) {
|
||||
return false;
|
||||
}
|
||||
mSubtypeEnablerPreference = new Preference(context);
|
||||
mSubtypeEnablerPreference
|
||||
.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
final CharSequence title = getSubtypeEnablerTitle(context);
|
||||
final Intent intent =
|
||||
new Intent(Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS);
|
||||
intent.putExtra(Settings.EXTRA_INPUT_METHOD_ID, mImi.getId());
|
||||
if (!TextUtils.isEmpty(title)) {
|
||||
intent.putExtra(Intent.EXTRA_TITLE, title);
|
||||
}
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
|
||||
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
context.startActivity(intent);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
prefScreen.addPreference(mSubtypeEnablerPreference);
|
||||
updateSubtypeEnabler();
|
||||
return true;
|
||||
}
|
||||
|
||||
private static InputMethodInfo getMyImi(Context context, InputMethodManager imm) {
|
||||
final List<InputMethodInfo> imis = imm.getInputMethodList();
|
||||
for (int i = 0; i < imis.size(); ++i) {
|
||||
final InputMethodInfo imi = imis.get(i);
|
||||
if (imis.get(i).getPackageName().equals(context.getPackageName())) {
|
||||
return imi;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String getEnabledSubtypesLabel(
|
||||
Context context, InputMethodManager imm, InputMethodInfo imi) {
|
||||
if (context == null || imm == null || imi == null) return null;
|
||||
final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(imi, true);
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final int N = subtypes.size();
|
||||
for (int i = 0; i < N; ++i) {
|
||||
final InputMethodSubtype subtype = subtypes.get(i);
|
||||
if (sb.length() > 0) {
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append(subtype.getDisplayName(context, imi.getPackageName(),
|
||||
imi.getServiceInfo().applicationInfo));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setInputMethodSettingsCategoryTitle(int resId) {
|
||||
mInputMethodSettingsCategoryTitleRes = resId;
|
||||
updateSubtypeEnabler();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setInputMethodSettingsCategoryTitle(CharSequence title) {
|
||||
mInputMethodSettingsCategoryTitleRes = 0;
|
||||
mInputMethodSettingsCategoryTitle = title;
|
||||
updateSubtypeEnabler();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setSubtypeEnablerTitle(int resId) {
|
||||
mSubtypeEnablerTitleRes = resId;
|
||||
updateSubtypeEnabler();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setSubtypeEnablerTitle(CharSequence title) {
|
||||
mSubtypeEnablerTitleRes = 0;
|
||||
mSubtypeEnablerTitle = title;
|
||||
updateSubtypeEnabler();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setSubtypeEnablerIcon(int resId) {
|
||||
mSubtypeEnablerIconRes = resId;
|
||||
updateSubtypeEnabler();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setSubtypeEnablerIcon(Drawable drawable) {
|
||||
mSubtypeEnablerIconRes = 0;
|
||||
mSubtypeEnablerIcon = drawable;
|
||||
updateSubtypeEnabler();
|
||||
}
|
||||
|
||||
private CharSequence getSubtypeEnablerTitle(Context context) {
|
||||
if (mSubtypeEnablerTitleRes != 0) {
|
||||
return context.getString(mSubtypeEnablerTitleRes);
|
||||
} else {
|
||||
return mSubtypeEnablerTitle;
|
||||
}
|
||||
}
|
||||
|
||||
public void updateSubtypeEnabler() {
|
||||
if (mSubtypeEnablerPreference != null) {
|
||||
if (mSubtypeEnablerTitleRes != 0) {
|
||||
mSubtypeEnablerPreference.setTitle(mSubtypeEnablerTitleRes);
|
||||
} else if (!TextUtils.isEmpty(mSubtypeEnablerTitle)) {
|
||||
mSubtypeEnablerPreference.setTitle(mSubtypeEnablerTitle);
|
||||
}
|
||||
final String summary = getEnabledSubtypesLabel(mContext, mImm, mImi);
|
||||
if (!TextUtils.isEmpty(summary)) {
|
||||
mSubtypeEnablerPreference.setSummary(summary);
|
||||
}
|
||||
if (mSubtypeEnablerIconRes != 0) {
|
||||
mSubtypeEnablerPreference.setIcon(mSubtypeEnablerIconRes);
|
||||
} else if (mSubtypeEnablerIcon != null) {
|
||||
mSubtypeEnablerPreference.setIcon(mSubtypeEnablerIcon);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is a part of the inputmethod-common static Java library.
|
||||
* The original source code can be found at frameworks/opt/inputmethodcommon of Android Open Source
|
||||
* Project.
|
||||
*/
|
||||
|
||||
package com.android.inputmethodcommon;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
/**
|
||||
* InputMethodSettingsInterface is the interface for adding IME related preferences to
|
||||
* PreferenceActivity or PreferenceFragment.
|
||||
*/
|
||||
public interface InputMethodSettingsInterface {
|
||||
/**
|
||||
* Sets the title for the input method settings category with a resource ID.
|
||||
* @param resId The resource ID of the title.
|
||||
*/
|
||||
public void setInputMethodSettingsCategoryTitle(int resId);
|
||||
|
||||
/**
|
||||
* Sets the title for the input method settings category with a CharSequence.
|
||||
* @param title The title for this preference.
|
||||
*/
|
||||
public void setInputMethodSettingsCategoryTitle(CharSequence title);
|
||||
|
||||
/**
|
||||
* Sets the title for the input method enabler preference for launching subtype enabler with a
|
||||
* resource ID.
|
||||
* @param resId The resource ID of the title.
|
||||
*/
|
||||
public void setSubtypeEnablerTitle(int resId);
|
||||
|
||||
/**
|
||||
* Sets the title for the input method enabler preference for launching subtype enabler with a
|
||||
* CharSequence.
|
||||
* @param title The title for this preference.
|
||||
*/
|
||||
public void setSubtypeEnablerTitle(CharSequence title);
|
||||
|
||||
/**
|
||||
* Sets the icon for the preference for launching subtype enabler with a resource ID.
|
||||
* @param resId The resource id of an optional icon for the preference.
|
||||
*/
|
||||
public void setSubtypeEnablerIcon(int resId);
|
||||
|
||||
/**
|
||||
* Sets the icon for the Preference for launching subtype enabler with a Drawable.
|
||||
* @param drawable The drawable of an optional icon for the preference.
|
||||
*/
|
||||
public void setSubtypeEnablerIcon(Drawable drawable);
|
||||
}
|
@ -0,0 +1,323 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package keepass2android.softkeyboard;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import keepass2android.softkeyboard.R;
|
||||
|
||||
public class CandidateView extends View {
|
||||
|
||||
private static final int OUT_OF_BOUNDS = -1;
|
||||
|
||||
private KP2AKeyboard mService;
|
||||
private List<String> mSuggestions;
|
||||
private int mSelectedIndex;
|
||||
private int mTouchX = OUT_OF_BOUNDS;
|
||||
private Drawable mSelectionHighlight;
|
||||
private boolean mTypedWordValid;
|
||||
|
||||
private Rect mBgPadding;
|
||||
|
||||
private static final int MAX_SUGGESTIONS = 32;
|
||||
private static final int SCROLL_PIXELS = 20;
|
||||
|
||||
private int[] mWordWidth = new int[MAX_SUGGESTIONS];
|
||||
private int[] mWordX = new int[MAX_SUGGESTIONS];
|
||||
|
||||
private static final int X_GAP = 10;
|
||||
|
||||
private static final List<String> EMPTY_LIST = new ArrayList<String>();
|
||||
|
||||
private int mColorNormal;
|
||||
private int mColorRecommended;
|
||||
private int mColorOther;
|
||||
private int mVerticalPadding;
|
||||
private Paint mPaint;
|
||||
private boolean mScrolled;
|
||||
private int mTargetScrollX;
|
||||
|
||||
private int mTotalWidth;
|
||||
|
||||
private GestureDetector mGestureDetector;
|
||||
|
||||
/**
|
||||
* Construct a CandidateView for showing suggested words for completion.
|
||||
* @param context
|
||||
* @param attrs
|
||||
*/
|
||||
public CandidateView(Context context) {
|
||||
super(context);
|
||||
mSelectionHighlight = context.getResources().getDrawable(
|
||||
android.R.drawable.list_selector_background);
|
||||
mSelectionHighlight.setState(new int[] {
|
||||
android.R.attr.state_enabled,
|
||||
android.R.attr.state_focused,
|
||||
android.R.attr.state_window_focused,
|
||||
android.R.attr.state_pressed
|
||||
});
|
||||
|
||||
Resources r = context.getResources();
|
||||
|
||||
setBackgroundColor(r.getColor(R.color.candidate_background));
|
||||
|
||||
mColorNormal = r.getColor(R.color.candidate_normal);
|
||||
mColorRecommended = r.getColor(R.color.candidate_recommended);
|
||||
mColorOther = r.getColor(R.color.candidate_other);
|
||||
mVerticalPadding = r.getDimensionPixelSize(R.dimen.candidate_vertical_padding);
|
||||
|
||||
mPaint = new Paint();
|
||||
mPaint.setColor(mColorNormal);
|
||||
mPaint.setAntiAlias(true);
|
||||
mPaint.setTextSize(r.getDimensionPixelSize(R.dimen.candidate_font_height));
|
||||
mPaint.setStrokeWidth(0);
|
||||
|
||||
mGestureDetector = new GestureDetector(new GestureDetector.SimpleOnGestureListener() {
|
||||
@Override
|
||||
public boolean onScroll(MotionEvent e1, MotionEvent e2,
|
||||
float distanceX, float distanceY) {
|
||||
mScrolled = true;
|
||||
int sx = getScrollX();
|
||||
sx += distanceX;
|
||||
if (sx < 0) {
|
||||
sx = 0;
|
||||
}
|
||||
if (sx + getWidth() > mTotalWidth) {
|
||||
sx -= distanceX;
|
||||
}
|
||||
mTargetScrollX = sx;
|
||||
scrollTo(sx, getScrollY());
|
||||
invalidate();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
setHorizontalFadingEdgeEnabled(true);
|
||||
setWillNotDraw(false);
|
||||
setHorizontalScrollBarEnabled(false);
|
||||
setVerticalScrollBarEnabled(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* A connection back to the service to communicate with the text field
|
||||
* @param listener
|
||||
*/
|
||||
public void setService(KP2AKeyboard listener) {
|
||||
mService = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int computeHorizontalScrollRange() {
|
||||
return mTotalWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int measuredWidth = resolveSize(50, widthMeasureSpec);
|
||||
|
||||
// Get the desired height of the icon menu view (last row of items does
|
||||
// not have a divider below)
|
||||
Rect padding = new Rect();
|
||||
mSelectionHighlight.getPadding(padding);
|
||||
final int desiredHeight = ((int)mPaint.getTextSize()) + mVerticalPadding
|
||||
+ padding.top + padding.bottom;
|
||||
|
||||
// Maximum possible width and desired height
|
||||
setMeasuredDimension(measuredWidth,
|
||||
resolveSize(desiredHeight, heightMeasureSpec));
|
||||
}
|
||||
|
||||
/**
|
||||
* If the canvas is null, then only touch calculations are performed to pick the target
|
||||
* candidate.
|
||||
*/
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (canvas != null) {
|
||||
super.onDraw(canvas);
|
||||
}
|
||||
mTotalWidth = 0;
|
||||
if (mSuggestions == null) return;
|
||||
|
||||
if (mBgPadding == null) {
|
||||
mBgPadding = new Rect(0, 0, 0, 0);
|
||||
if (getBackground() != null) {
|
||||
getBackground().getPadding(mBgPadding);
|
||||
}
|
||||
}
|
||||
int x = 0;
|
||||
final int count = mSuggestions.size();
|
||||
final int height = getHeight();
|
||||
final Rect bgPadding = mBgPadding;
|
||||
final Paint paint = mPaint;
|
||||
final int touchX = mTouchX;
|
||||
final int scrollX = getScrollX();
|
||||
final boolean scrolled = mScrolled;
|
||||
final boolean typedWordValid = mTypedWordValid;
|
||||
final int y = (int) (((height - mPaint.getTextSize()) / 2) - mPaint.ascent());
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
String suggestion = mSuggestions.get(i);
|
||||
float textWidth = paint.measureText(suggestion);
|
||||
final int wordWidth = (int) textWidth + X_GAP * 2;
|
||||
|
||||
mWordX[i] = x;
|
||||
mWordWidth[i] = wordWidth;
|
||||
paint.setColor(mColorNormal);
|
||||
if (touchX + scrollX >= x && touchX + scrollX < x + wordWidth && !scrolled) {
|
||||
if (canvas != null) {
|
||||
canvas.translate(x, 0);
|
||||
mSelectionHighlight.setBounds(0, bgPadding.top, wordWidth, height);
|
||||
mSelectionHighlight.draw(canvas);
|
||||
canvas.translate(-x, 0);
|
||||
}
|
||||
mSelectedIndex = i;
|
||||
}
|
||||
|
||||
if (canvas != null) {
|
||||
if ((i == 1 && !typedWordValid) || (i == 0 && typedWordValid)) {
|
||||
paint.setFakeBoldText(true);
|
||||
paint.setColor(mColorRecommended);
|
||||
} else if (i != 0) {
|
||||
paint.setColor(mColorOther);
|
||||
}
|
||||
canvas.drawText(suggestion, x + X_GAP, y, paint);
|
||||
paint.setColor(mColorOther);
|
||||
canvas.drawLine(x + wordWidth + 0.5f, bgPadding.top,
|
||||
x + wordWidth + 0.5f, height + 1, paint);
|
||||
paint.setFakeBoldText(false);
|
||||
}
|
||||
x += wordWidth;
|
||||
}
|
||||
mTotalWidth = x;
|
||||
if (mTargetScrollX != getScrollX()) {
|
||||
scrollToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
private void scrollToTarget() {
|
||||
int sx = getScrollX();
|
||||
if (mTargetScrollX > sx) {
|
||||
sx += SCROLL_PIXELS;
|
||||
if (sx >= mTargetScrollX) {
|
||||
sx = mTargetScrollX;
|
||||
requestLayout();
|
||||
}
|
||||
} else {
|
||||
sx -= SCROLL_PIXELS;
|
||||
if (sx <= mTargetScrollX) {
|
||||
sx = mTargetScrollX;
|
||||
requestLayout();
|
||||
}
|
||||
}
|
||||
scrollTo(sx, getScrollY());
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setSuggestions(List<String> suggestions, boolean completions,
|
||||
boolean typedWordValid) {
|
||||
clear();
|
||||
if (suggestions != null) {
|
||||
mSuggestions = new ArrayList<String>(suggestions);
|
||||
}
|
||||
mTypedWordValid = typedWordValid;
|
||||
scrollTo(0, 0);
|
||||
mTargetScrollX = 0;
|
||||
// Compute the total width
|
||||
onDraw(null);
|
||||
invalidate();
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
mSuggestions = EMPTY_LIST;
|
||||
mTouchX = OUT_OF_BOUNDS;
|
||||
mSelectedIndex = -1;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent me) {
|
||||
|
||||
if (mGestureDetector.onTouchEvent(me)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int action = me.getAction();
|
||||
int x = (int) me.getX();
|
||||
int y = (int) me.getY();
|
||||
mTouchX = x;
|
||||
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mScrolled = false;
|
||||
invalidate();
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (y <= 0) {
|
||||
// Fling up!?
|
||||
if (mSelectedIndex >= 0) {
|
||||
mService.pickSuggestionManually(mSelectedIndex);
|
||||
mSelectedIndex = -1;
|
||||
}
|
||||
}
|
||||
invalidate();
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
if (!mScrolled) {
|
||||
if (mSelectedIndex >= 0) {
|
||||
mService.pickSuggestionManually(mSelectedIndex);
|
||||
}
|
||||
}
|
||||
mSelectedIndex = -1;
|
||||
removeHighlight();
|
||||
requestLayout();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* For flick through from keyboard, call this method with the x coordinate of the flick
|
||||
* gesture.
|
||||
* @param x
|
||||
*/
|
||||
public void takeSuggestionAt(float x) {
|
||||
mTouchX = (int) x;
|
||||
// To detect candidate
|
||||
onDraw(null);
|
||||
if (mSelectedIndex >= 0) {
|
||||
mService.pickSuggestionManually(mSelectedIndex);
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private void removeHighlight() {
|
||||
mTouchX = OUT_OF_BOUNDS;
|
||||
invalidate();
|
||||
}
|
||||
}
|
@ -0,0 +1,645 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package keepass2android.softkeyboard;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.inputmethodservice.InputMethodService;
|
||||
import android.inputmethodservice.Keyboard;
|
||||
import android.inputmethodservice.KeyboardView;
|
||||
import android.text.InputType;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.CompletionInfo;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import keepass2android.softkeyboard.R;
|
||||
|
||||
/**
|
||||
* Example of writing an input method for a soft keyboard. This code is
|
||||
* focused on simplicity over completeness, so it should in no way be considered
|
||||
* to be a complete soft keyboard implementation. Its purpose is to provide
|
||||
* a basic example for how you would get started writing an input method, to
|
||||
* be fleshed out as appropriate.
|
||||
*/
|
||||
public class KP2AKeyboard extends InputMethodService
|
||||
implements KeyboardView.OnKeyboardActionListener {
|
||||
static final boolean DEBUG = false;
|
||||
|
||||
private InputMethodManager mInputMethodManager;
|
||||
|
||||
private LatinKeyboardView mInputView;
|
||||
private CandidateView mCandidateView;
|
||||
private CompletionInfo[] mCompletions;
|
||||
|
||||
private StringBuilder mComposing = new StringBuilder();
|
||||
private boolean mPredictionOn;
|
||||
private boolean mCompletionOn;
|
||||
private int mLastDisplayWidth;
|
||||
private boolean mCapsLock;
|
||||
private long mLastShiftTime;
|
||||
private long mMetaState;
|
||||
|
||||
private LatinKeyboard mSymbolsKeyboard;
|
||||
private LatinKeyboard mSymbolsShiftedKeyboard;
|
||||
private LatinKeyboard mQwertyKeyboard;
|
||||
|
||||
private LatinKeyboard mCurKeyboard;
|
||||
|
||||
private String mWordSeparators;
|
||||
|
||||
/**
|
||||
* Main initialization of the input method component. Be sure to call
|
||||
* to super class.
|
||||
*/
|
||||
@Override public void onCreate() {
|
||||
super.onCreate();
|
||||
mInputMethodManager = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
|
||||
mWordSeparators = getResources().getString(R.string.word_separators);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the point where you can do all of your UI initialization. It
|
||||
* is called after creation and any configuration change.
|
||||
*/
|
||||
@Override public void onInitializeInterface() {
|
||||
if (mQwertyKeyboard != null) {
|
||||
// Configuration changes can happen after the keyboard gets recreated,
|
||||
// so we need to be able to re-build the keyboards if the available
|
||||
// space has changed.
|
||||
int displayWidth = getMaxWidth();
|
||||
if (displayWidth == mLastDisplayWidth) return;
|
||||
mLastDisplayWidth = displayWidth;
|
||||
}
|
||||
mQwertyKeyboard = new LatinKeyboard(this, R.xml.qwerty);
|
||||
mSymbolsKeyboard = new LatinKeyboard(this, R.xml.symbols);
|
||||
mSymbolsShiftedKeyboard = new LatinKeyboard(this, R.xml.symbols_shift);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the framework when your view for creating input needs to
|
||||
* be generated. This will be called the first time your input method
|
||||
* is displayed, and every time it needs to be re-created such as due to
|
||||
* a configuration change.
|
||||
*/
|
||||
@Override public View onCreateInputView() {
|
||||
mInputView = (LatinKeyboardView) getLayoutInflater().inflate(
|
||||
R.layout.input, null);
|
||||
mInputView.setOnKeyboardActionListener(this);
|
||||
mInputView.setKeyboard(mQwertyKeyboard);
|
||||
return mInputView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the framework when your view for showing candidates needs to
|
||||
* be generated, like {@link #onCreateInputView}.
|
||||
*/
|
||||
@Override public View onCreateCandidatesView() {
|
||||
mCandidateView = new CandidateView(this);
|
||||
mCandidateView.setService(this);
|
||||
return mCandidateView;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the main point where we do our initialization of the input method
|
||||
* to begin operating on an application. At this point we have been
|
||||
* bound to the client, and are now receiving all of the detailed information
|
||||
* about the target of our edits.
|
||||
*/
|
||||
@Override public void onStartInput(EditorInfo attribute, boolean restarting) {
|
||||
super.onStartInput(attribute, restarting);
|
||||
|
||||
// Reset our state. We want to do this even if restarting, because
|
||||
// the underlying state of the text editor could have changed in any way.
|
||||
mComposing.setLength(0);
|
||||
updateCandidates();
|
||||
|
||||
if (!restarting) {
|
||||
// Clear shift states.
|
||||
mMetaState = 0;
|
||||
}
|
||||
|
||||
mPredictionOn = false;
|
||||
mCompletionOn = false;
|
||||
mCompletions = null;
|
||||
|
||||
// We are now going to initialize our state based on the type of
|
||||
// text being edited.
|
||||
switch (attribute.inputType & InputType.TYPE_MASK_CLASS) {
|
||||
case InputType.TYPE_CLASS_NUMBER:
|
||||
case InputType.TYPE_CLASS_DATETIME:
|
||||
// Numbers and dates default to the symbols keyboard, with
|
||||
// no extra features.
|
||||
mCurKeyboard = mSymbolsKeyboard;
|
||||
break;
|
||||
|
||||
case InputType.TYPE_CLASS_PHONE:
|
||||
// Phones will also default to the symbols keyboard, though
|
||||
// often you will want to have a dedicated phone keyboard.
|
||||
mCurKeyboard = mSymbolsKeyboard;
|
||||
break;
|
||||
|
||||
case InputType.TYPE_CLASS_TEXT:
|
||||
// This is general text editing. We will default to the
|
||||
// normal alphabetic keyboard, and assume that we should
|
||||
// be doing predictive text (showing candidates as the
|
||||
// user types).
|
||||
mCurKeyboard = mQwertyKeyboard;
|
||||
mPredictionOn = true;
|
||||
|
||||
// We now look for a few special variations of text that will
|
||||
// modify our behavior.
|
||||
int variation = attribute.inputType & InputType.TYPE_MASK_VARIATION;
|
||||
if (variation == InputType.TYPE_TEXT_VARIATION_PASSWORD ||
|
||||
variation == InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) {
|
||||
// Do not display predictions / what the user is typing
|
||||
// when they are entering a password.
|
||||
mPredictionOn = false;
|
||||
}
|
||||
|
||||
if (variation == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
|
||||
|| variation == InputType.TYPE_TEXT_VARIATION_URI
|
||||
|| variation == InputType.TYPE_TEXT_VARIATION_FILTER) {
|
||||
// Our predictions are not useful for e-mail addresses
|
||||
// or URIs.
|
||||
mPredictionOn = false;
|
||||
}
|
||||
|
||||
if ((attribute.inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) {
|
||||
// If this is an auto-complete text view, then our predictions
|
||||
// will not be shown and instead we will allow the editor
|
||||
// to supply their own. We only show the editor's
|
||||
// candidates when in fullscreen mode, otherwise relying
|
||||
// own it displaying its own UI.
|
||||
mPredictionOn = false;
|
||||
mCompletionOn = isFullscreenMode();
|
||||
}
|
||||
|
||||
// We also want to look at the current state of the editor
|
||||
// to decide whether our alphabetic keyboard should start out
|
||||
// shifted.
|
||||
updateShiftKeyState(attribute);
|
||||
break;
|
||||
|
||||
default:
|
||||
// For all unknown input types, default to the alphabetic
|
||||
// keyboard with no special features.
|
||||
mCurKeyboard = mQwertyKeyboard;
|
||||
updateShiftKeyState(attribute);
|
||||
}
|
||||
|
||||
// Update the label on the enter key, depending on what the application
|
||||
// says it will do.
|
||||
mCurKeyboard.setImeOptions(getResources(), attribute.imeOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when the user is done editing a field. We can use
|
||||
* this to reset our state.
|
||||
*/
|
||||
@Override public void onFinishInput() {
|
||||
super.onFinishInput();
|
||||
|
||||
// Clear current composing text and candidates.
|
||||
mComposing.setLength(0);
|
||||
updateCandidates();
|
||||
|
||||
// We only hide the candidates window when finishing input on
|
||||
// a particular editor, to avoid popping the underlying application
|
||||
// up and down if the user is entering text into the bottom of
|
||||
// its window.
|
||||
setCandidatesViewShown(false);
|
||||
|
||||
mCurKeyboard = mQwertyKeyboard;
|
||||
if (mInputView != null) {
|
||||
mInputView.closing();
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void onStartInputView(EditorInfo attribute, boolean restarting) {
|
||||
super.onStartInputView(attribute, restarting);
|
||||
// Apply the selected keyboard to the input view.
|
||||
mInputView.setKeyboard(mCurKeyboard);
|
||||
mInputView.closing();
|
||||
//final InputMethodSubtype subtype = mInputMethodManager.getCurrentInputMethodSubtype();
|
||||
//mInputView.setSubtypeOnSpaceKey(subtype);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) {
|
||||
mInputView.setSubtypeOnSpaceKey(subtype);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deal with the editor reporting movement of its cursor.
|
||||
*/
|
||||
@Override public void onUpdateSelection(int oldSelStart, int oldSelEnd,
|
||||
int newSelStart, int newSelEnd,
|
||||
int candidatesStart, int candidatesEnd) {
|
||||
super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
|
||||
candidatesStart, candidatesEnd);
|
||||
|
||||
// If the current selection in the text view changes, we should
|
||||
// clear whatever candidate text we have.
|
||||
if (mComposing.length() > 0 && (newSelStart != candidatesEnd
|
||||
|| newSelEnd != candidatesEnd)) {
|
||||
mComposing.setLength(0);
|
||||
updateCandidates();
|
||||
InputConnection ic = getCurrentInputConnection();
|
||||
if (ic != null) {
|
||||
ic.finishComposingText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This tells us about completions that the editor has determined based
|
||||
* on the current text in it. We want to use this in fullscreen mode
|
||||
* to show the completions ourself, since the editor can not be seen
|
||||
* in that situation.
|
||||
*/
|
||||
@Override public void onDisplayCompletions(CompletionInfo[] completions) {
|
||||
if (mCompletionOn) {
|
||||
mCompletions = completions;
|
||||
if (completions == null) {
|
||||
setSuggestions(null, false, false);
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> stringList = new ArrayList<String>();
|
||||
for (int i = 0; i < completions.length; i++) {
|
||||
CompletionInfo ci = completions[i];
|
||||
if (ci != null) stringList.add(ci.getText().toString());
|
||||
}
|
||||
setSuggestions(stringList, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Use this to monitor key events being delivered to the application.
|
||||
* We get first crack at them, and can either resume them or let them
|
||||
* continue to the app.
|
||||
*/
|
||||
@Override public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_BACK:
|
||||
// The InputMethodService already takes care of the back
|
||||
// key for us, to dismiss the input method if it is shown.
|
||||
// However, our keyboard could be showing a pop-up window
|
||||
// that back should dismiss, so we first allow it to do that.
|
||||
if (event.getRepeatCount() == 0 && mInputView != null) {
|
||||
if (mInputView.handleBack()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyEvent.KEYCODE_DEL:
|
||||
// Special handling of the delete key: if we currently are
|
||||
// composing text for the user, we want to modify that instead
|
||||
// of let the application to the delete itself.
|
||||
if (mComposing.length() > 0) {
|
||||
onKey(Keyboard.KEYCODE_DELETE, null);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyEvent.KEYCODE_ENTER:
|
||||
// Let the underlying text editor always handle these.
|
||||
return false;
|
||||
|
||||
default:
|
||||
|
||||
}
|
||||
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper function to commit any text being composed in to the editor.
|
||||
*/
|
||||
private void commitTyped(InputConnection inputConnection) {
|
||||
if (mComposing.length() > 0) {
|
||||
inputConnection.commitText(mComposing, mComposing.length());
|
||||
mComposing.setLength(0);
|
||||
updateCandidates();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to update the shift state of our keyboard based on the initial
|
||||
* editor state.
|
||||
*/
|
||||
private void updateShiftKeyState(EditorInfo attr) {
|
||||
if (attr != null
|
||||
&& mInputView != null && mQwertyKeyboard == mInputView.getKeyboard()) {
|
||||
int caps = 0;
|
||||
EditorInfo ei = getCurrentInputEditorInfo();
|
||||
if (ei != null && ei.inputType != InputType.TYPE_NULL) {
|
||||
caps = getCurrentInputConnection().getCursorCapsMode(attr.inputType);
|
||||
}
|
||||
mInputView.setShifted(mCapsLock || caps != 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to determine if a given character code is alphabetic.
|
||||
*/
|
||||
private boolean isAlphabet(int code) {
|
||||
if (Character.isLetter(code)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to send a key down / key up pair to the current editor.
|
||||
*/
|
||||
private void keyDownUp(int keyEventCode) {
|
||||
getCurrentInputConnection().sendKeyEvent(
|
||||
new KeyEvent(KeyEvent.ACTION_DOWN, keyEventCode));
|
||||
getCurrentInputConnection().sendKeyEvent(
|
||||
new KeyEvent(KeyEvent.ACTION_UP, keyEventCode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to send a character to the editor as raw key events.
|
||||
*/
|
||||
private void sendKey(int keyCode) {
|
||||
switch (keyCode) {
|
||||
case '\n':
|
||||
keyDownUp(KeyEvent.KEYCODE_ENTER);
|
||||
break;
|
||||
default:
|
||||
if (keyCode >= '0' && keyCode <= '9') {
|
||||
keyDownUp(keyCode - '0' + KeyEvent.KEYCODE_0);
|
||||
} else {
|
||||
getCurrentInputConnection().commitText(String.valueOf((char) keyCode), 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation of KeyboardViewListener
|
||||
|
||||
public void onKey(int primaryCode, int[] keyCodes) {
|
||||
if (isWordSeparator(primaryCode)) {
|
||||
// Handle separator
|
||||
if (mComposing.length() > 0) {
|
||||
commitTyped(getCurrentInputConnection());
|
||||
}
|
||||
sendKey(primaryCode);
|
||||
updateShiftKeyState(getCurrentInputEditorInfo());
|
||||
} else if (primaryCode == Keyboard.KEYCODE_DELETE) {
|
||||
handleBackspace();
|
||||
} else if (primaryCode == Keyboard.KEYCODE_SHIFT) {
|
||||
handleShift();
|
||||
} else if (primaryCode == Keyboard.KEYCODE_CANCEL) {
|
||||
handleClose();
|
||||
return;
|
||||
} else if (primaryCode == LatinKeyboardView.KEYCODE_KP2A) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
final CharSequence[] items = {"Gallery Image Menu!", "hello你好", "View pattern", "Delete pattern", "Locate pattern in list view", "Row Counter (with pattern)", "Share Pattern", "Share Image"};
|
||||
builder.setTitle("Keepass2Android");
|
||||
//builder.setMessage("What do you want to type securely?");
|
||||
builder.setItems(items, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int item) {
|
||||
|
||||
getCurrentInputConnection().commitText(items[item],0);
|
||||
|
||||
if (item == 0){
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
// Add the buttons
|
||||
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
// User cancelled the dialog
|
||||
}
|
||||
});
|
||||
// Set other dialog properties
|
||||
|
||||
// Create the AlertDialog
|
||||
AlertDialog dialog = builder.create();
|
||||
Window window = dialog.getWindow();
|
||||
WindowManager.LayoutParams lp = window.getAttributes();
|
||||
lp.token = mInputView.getWindowToken();
|
||||
lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
|
||||
window.setAttributes(lp);
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
|
||||
|
||||
dialog.show();
|
||||
} else if (primaryCode == LatinKeyboardView.KEYCODE_OPTIONS) {
|
||||
// Show a menu or somethin'
|
||||
} else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE
|
||||
&& mInputView != null) {
|
||||
Keyboard current = mInputView.getKeyboard();
|
||||
if (current == mSymbolsKeyboard || current == mSymbolsShiftedKeyboard) {
|
||||
current = mQwertyKeyboard;
|
||||
} else {
|
||||
current = mSymbolsKeyboard;
|
||||
}
|
||||
mInputView.setKeyboard(current);
|
||||
if (current == mSymbolsKeyboard) {
|
||||
current.setShifted(false);
|
||||
}
|
||||
} else {
|
||||
handleCharacter(primaryCode, keyCodes);
|
||||
//mCapsLock = false;
|
||||
//mInputView.setShifted(mCapsLock);
|
||||
updateShiftKeyState(getCurrentInputEditorInfo());
|
||||
}
|
||||
}
|
||||
|
||||
public void onText(CharSequence text) {
|
||||
InputConnection ic = getCurrentInputConnection();
|
||||
if (ic == null) return;
|
||||
ic.beginBatchEdit();
|
||||
if (mComposing.length() > 0) {
|
||||
commitTyped(ic);
|
||||
}
|
||||
ic.commitText(text, 0);
|
||||
ic.endBatchEdit();
|
||||
updateShiftKeyState(getCurrentInputEditorInfo());
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the list of available candidates from the current composing
|
||||
* text. This will need to be filled in by however you are determining
|
||||
* candidates.
|
||||
*/
|
||||
private void updateCandidates() {
|
||||
if (!mCompletionOn) {
|
||||
if (mComposing.length() > 0) {
|
||||
ArrayList<String> list = new ArrayList<String>();
|
||||
list.add(mComposing.toString());
|
||||
setSuggestions(list, true, true);
|
||||
} else {
|
||||
setSuggestions(null, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setSuggestions(List<String> suggestions, boolean completions,
|
||||
boolean typedWordValid) {
|
||||
if (suggestions != null && suggestions.size() > 0) {
|
||||
setCandidatesViewShown(true);
|
||||
} else if (isExtractViewShown()) {
|
||||
setCandidatesViewShown(true);
|
||||
}
|
||||
if (mCandidateView != null) {
|
||||
mCandidateView.setSuggestions(suggestions, completions, typedWordValid);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleBackspace() {
|
||||
final int length = mComposing.length();
|
||||
if (length > 1) {
|
||||
mComposing.delete(length - 1, length);
|
||||
getCurrentInputConnection().setComposingText(mComposing, 1);
|
||||
updateCandidates();
|
||||
} else if (length > 0) {
|
||||
mComposing.setLength(0);
|
||||
getCurrentInputConnection().commitText("", 0);
|
||||
updateCandidates();
|
||||
} else {
|
||||
keyDownUp(KeyEvent.KEYCODE_DEL);
|
||||
}
|
||||
updateShiftKeyState(getCurrentInputEditorInfo());
|
||||
}
|
||||
|
||||
private void handleShift() {
|
||||
if (mInputView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Keyboard currentKeyboard = mInputView.getKeyboard();
|
||||
if (mQwertyKeyboard == currentKeyboard) {
|
||||
// Alphabet keyboard
|
||||
checkToggleCapsLock();
|
||||
mInputView.setShifted(mCapsLock || !mInputView.isShifted());
|
||||
|
||||
|
||||
} else if (currentKeyboard == mSymbolsKeyboard) {
|
||||
mSymbolsKeyboard.setShifted(true);
|
||||
mInputView.setKeyboard(mSymbolsShiftedKeyboard);
|
||||
mSymbolsShiftedKeyboard.setShifted(true);
|
||||
} else if (currentKeyboard == mSymbolsShiftedKeyboard) {
|
||||
mSymbolsShiftedKeyboard.setShifted(false);
|
||||
mInputView.setKeyboard(mSymbolsKeyboard);
|
||||
mSymbolsKeyboard.setShifted(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleCharacter(int primaryCode, int[] keyCodes) {
|
||||
if (isInputViewShown()) {
|
||||
if (mInputView.isShifted()) {
|
||||
primaryCode = Character.toUpperCase(primaryCode);
|
||||
}
|
||||
}
|
||||
if (isAlphabet(primaryCode) && mPredictionOn) {
|
||||
mComposing.append((char) primaryCode);
|
||||
getCurrentInputConnection().setComposingText(mComposing, 1);
|
||||
updateShiftKeyState(getCurrentInputEditorInfo());
|
||||
updateCandidates();
|
||||
} else {
|
||||
getCurrentInputConnection().commitText(
|
||||
String.valueOf((char) primaryCode), 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleClose() {
|
||||
commitTyped(getCurrentInputConnection());
|
||||
requestHideSelf(0);
|
||||
mInputView.closing();
|
||||
}
|
||||
|
||||
private void checkToggleCapsLock() {
|
||||
long now = System.currentTimeMillis();
|
||||
if (mLastShiftTime + 800 > now) {
|
||||
mCapsLock = !mCapsLock;
|
||||
mLastShiftTime = 0;
|
||||
} else {
|
||||
mLastShiftTime = now;
|
||||
}
|
||||
}
|
||||
|
||||
private String getWordSeparators() {
|
||||
return mWordSeparators;
|
||||
}
|
||||
|
||||
public boolean isWordSeparator(int code) {
|
||||
String separators = getWordSeparators();
|
||||
return separators.contains(String.valueOf((char)code));
|
||||
}
|
||||
|
||||
public void pickDefaultCandidate() {
|
||||
pickSuggestionManually(0);
|
||||
}
|
||||
|
||||
public void pickSuggestionManually(int index) {
|
||||
if (mCompletionOn && mCompletions != null && index >= 0
|
||||
&& index < mCompletions.length) {
|
||||
CompletionInfo ci = mCompletions[index];
|
||||
getCurrentInputConnection().commitCompletion(ci);
|
||||
if (mCandidateView != null) {
|
||||
mCandidateView.clear();
|
||||
}
|
||||
updateShiftKeyState(getCurrentInputEditorInfo());
|
||||
} else if (mComposing.length() > 0) {
|
||||
// If we were generating candidate suggestions for the current
|
||||
// text, we would commit one of them here. But for this sample,
|
||||
// we will just commit the current text.
|
||||
commitTyped(getCurrentInputConnection());
|
||||
}
|
||||
}
|
||||
|
||||
public void swipeRight() {
|
||||
if (mCompletionOn) {
|
||||
pickDefaultCandidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void swipeLeft() {
|
||||
handleBackspace();
|
||||
}
|
||||
|
||||
public void swipeDown() {
|
||||
handleClose();
|
||||
}
|
||||
|
||||
public void swipeUp() {
|
||||
}
|
||||
|
||||
public void onPress(int primaryCode) {
|
||||
}
|
||||
|
||||
public void onRelease(int primaryCode) {
|
||||
}
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package keepass2android.softkeyboard;
|
||||
|
||||
import keepass2android.softkeyboard.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.inputmethodservice.Keyboard;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
|
||||
public class LatinKeyboard extends Keyboard {
|
||||
|
||||
private Key mEnterKey;
|
||||
private Key mSpaceKey;
|
||||
|
||||
public LatinKeyboard(Context context, int xmlLayoutResId) {
|
||||
super(context, xmlLayoutResId);
|
||||
}
|
||||
|
||||
public LatinKeyboard(Context context, int layoutTemplateResId,
|
||||
CharSequence characters, int columns, int horizontalPadding) {
|
||||
super(context, layoutTemplateResId, characters, columns, horizontalPadding);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Key createKeyFromXml(Resources res, Row parent, int x, int y,
|
||||
XmlResourceParser parser) {
|
||||
Key key = new LatinKey(res, parent, x, y, parser);
|
||||
if (key.codes[0] == 10) {
|
||||
mEnterKey = key;
|
||||
} else if (key.codes[0] == ' ') {
|
||||
mSpaceKey = key;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* This looks at the ime options given by the current editor, to set the
|
||||
* appropriate label on the keyboard's enter key (if it has one).
|
||||
*/
|
||||
void setImeOptions(Resources res, int options) {
|
||||
if (mEnterKey == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (options&(EditorInfo.IME_MASK_ACTION|EditorInfo.IME_FLAG_NO_ENTER_ACTION)) {
|
||||
case EditorInfo.IME_ACTION_GO:
|
||||
mEnterKey.iconPreview = null;
|
||||
mEnterKey.icon = null;
|
||||
mEnterKey.label = res.getText(R.string.label_go_key);
|
||||
break;
|
||||
case EditorInfo.IME_ACTION_NEXT:
|
||||
mEnterKey.iconPreview = null;
|
||||
mEnterKey.icon = null;
|
||||
mEnterKey.label = res.getText(R.string.label_next_key);
|
||||
break;
|
||||
case EditorInfo.IME_ACTION_SEARCH:
|
||||
mEnterKey.icon = res.getDrawable(R.drawable.sym_keyboard_search);
|
||||
mEnterKey.label = null;
|
||||
break;
|
||||
case EditorInfo.IME_ACTION_SEND:
|
||||
mEnterKey.iconPreview = null;
|
||||
mEnterKey.icon = null;
|
||||
mEnterKey.label = res.getText(R.string.label_send_key);
|
||||
break;
|
||||
default:
|
||||
mEnterKey.icon = res.getDrawable(R.drawable.sym_keyboard_return);
|
||||
mEnterKey.label = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setSpaceIcon(final Drawable icon) {
|
||||
if (mSpaceKey != null) {
|
||||
mSpaceKey.icon = icon;
|
||||
}
|
||||
}
|
||||
|
||||
static class LatinKey extends Keyboard.Key {
|
||||
|
||||
public LatinKey(Resources res, Keyboard.Row parent, int x, int y, XmlResourceParser parser) {
|
||||
super(res, parent, x, y, parser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overriding this method so that we can reduce the target area for the key that
|
||||
* closes the keyboard.
|
||||
*/
|
||||
@Override
|
||||
public boolean isInside(int x, int y) {
|
||||
return super.isInside(x, codes[0] == KEYCODE_CANCEL ? y - 10 : y);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package keepass2android.softkeyboard;
|
||||
|
||||
import android.content.Context;
|
||||
import android.inputmethodservice.Keyboard;
|
||||
import android.inputmethodservice.Keyboard.Key;
|
||||
import android.inputmethodservice.KeyboardView;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
|
||||
public class LatinKeyboardView extends KeyboardView {
|
||||
|
||||
static final int KEYCODE_OPTIONS = -100;
|
||||
static final int KEYCODE_KP2A = -101;
|
||||
|
||||
public LatinKeyboardView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public LatinKeyboardView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onLongPress(Key key) {
|
||||
if (key.codes[0] == Keyboard.KEYCODE_CANCEL) {
|
||||
getOnKeyboardActionListener().onKey(KEYCODE_OPTIONS, null);
|
||||
return true;
|
||||
} else {
|
||||
return super.onLongPress(key);
|
||||
}
|
||||
}
|
||||
|
||||
void setSubtypeOnSpaceKey(final InputMethodSubtype subtype) {
|
||||
//final LatinKeyboard keyboard = (LatinKeyboard)getKeyboard();
|
||||
//keyboard.setSpaceIcon(getResources().getDrawable(subtype.getIconResId()));
|
||||
//invalidateAllKeys();
|
||||
}
|
||||
}
|
8
src/java/kbbridge/.classpath
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
33
src/java/kbbridge/.project
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>KP2ASoftKeyboardBridge</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
17
src/java/kbbridge/AndroidManifest.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="keepass2android.kbbridge"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="8"
|
||||
android:targetSdkVersion="17" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme" >
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -0,0 +1,6 @@
|
||||
/** Automatically generated file. DO NOT MODIFY */
|
||||
package keepass2android.kbbridge;
|
||||
|
||||
public final class BuildConfig {
|
||||
public final static boolean DEBUG = true;
|
||||
}
|
47
src/java/kbbridge/gen/keepass2android/kbbridge/R.java
Normal file
@ -0,0 +1,47 @@
|
||||
/* AUTO-GENERATED FILE. DO NOT MODIFY.
|
||||
*
|
||||
* This class was automatically generated by the
|
||||
* aapt tool from the resource data it found. It
|
||||
* should not be modified by hand.
|
||||
*/
|
||||
|
||||
package keepass2android.kbbridge;
|
||||
|
||||
public final class R {
|
||||
public static final class attr {
|
||||
}
|
||||
public static final class drawable {
|
||||
public static int ic_launcher=0x7f020000;
|
||||
}
|
||||
public static final class string {
|
||||
public static int app_name=0x7f030000;
|
||||
}
|
||||
public static final class style {
|
||||
/**
|
||||
Base application theme, dependent on API level. This theme is replaced
|
||||
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
|
||||
|
||||
|
||||
Theme customizations available in newer API levels can go in
|
||||
res/values-vXX/styles.xml, while customizations related to
|
||||
backward-compatibility can go here.
|
||||
|
||||
|
||||
Base application theme for API 11+. This theme completely replaces
|
||||
AppBaseTheme from res/values/styles.xml on API 11+ devices.
|
||||
|
||||
API 11 theme customizations can go here.
|
||||
|
||||
Base application theme for API 14+. This theme completely replaces
|
||||
AppBaseTheme from BOTH res/values/styles.xml and
|
||||
res/values-v11/styles.xml on API 14+ devices.
|
||||
|
||||
API 14 theme customizations can go here.
|
||||
*/
|
||||
public static int AppBaseTheme=0x7f040000;
|
||||
/** Application theme.
|
||||
All customizations that are NOT specific to a particular API-level can go here.
|
||||
*/
|
||||
public static int AppTheme=0x7f040001;
|
||||
}
|
||||
}
|
20
src/java/kbbridge/proguard-project.txt
Normal file
@ -0,0 +1,20 @@
|
||||
# To enable ProGuard in your project, edit project.properties
|
||||
# to define the proguard.config property as described in that file.
|
||||
#
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in ${sdk.dir}/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the ProGuard
|
||||
# include property in project.properties.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
15
src/java/kbbridge/project.properties
Normal file
@ -0,0 +1,15 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system edit
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
#
|
||||
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||
|
||||
# Project target.
|
||||
target=android-14
|
||||
android.library=true
|
5
src/java/kbbridge/res/values/strings.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<resources>
|
||||
|
||||
<string name="app_name">KP2ASoftKeyboardBridge</string>
|
||||
|
||||
</resources>
|
20
src/java/kbbridge/res/values/styles.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<resources>
|
||||
|
||||
<!--
|
||||
Base application theme, dependent on API level. This theme is replaced
|
||||
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
|
||||
-->
|
||||
<style name="AppBaseTheme" parent="android:Theme.Light">
|
||||
<!--
|
||||
Theme customizations available in newer API levels can go in
|
||||
res/values-vXX/styles.xml, while customizations related to
|
||||
backward-compatibility can go here.
|
||||
-->
|
||||
</style>
|
||||
|
||||
<!-- Application theme. -->
|
||||
<style name="AppTheme" parent="AppBaseTheme">
|
||||
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
@ -0,0 +1,6 @@
|
||||
|
||||
package keepass2android.kbbridge;
|
||||
import java.util.HashMap;
|
||||
public class KeyboardData {
|
||||
public static HashMap<String, String> availableFields = new HashMap<String, String>();
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package keepass2android.kbbridge;
|
||||
import java.util.HashMap;
|
||||
public class KeyboardDataBuilder {
|
||||
private HashMap<String, String> availableFields = new HashMap<String, String>();
|
||||
|
||||
public void addPair(String displayName, String valueToType)
|
||||
{
|
||||
availableFields.put(displayName, valueToType);
|
||||
}
|
||||
|
||||
public void commit()
|
||||
{
|
||||
KeyboardData.availableFields = this.availableFields;
|
||||
}
|
||||
}
|