mirror of
https://gitlab.com/android_translation_layer/android_translation_layer.git
synced 2025-04-28 12:17:57 +03:00
ATLKeyboard: Integrate with phosh and wayland IME
This commit is contained in:
parent
80ec4bd02a
commit
882cd1b471
14 changed files with 1227 additions and 24 deletions
22
meson.build
22
meson.build
|
@ -45,6 +45,16 @@ portal_openuri = gnome.gdbus_codegen('portal-openuri',
|
||||||
'src/api-impl-jni/content/org.freedesktop.portal.OpenURI.xml',
|
'src/api-impl-jni/content/org.freedesktop.portal.OpenURI.xml',
|
||||||
interface_prefix: 'org.freedesktop.portal')
|
interface_prefix: 'org.freedesktop.portal')
|
||||||
|
|
||||||
|
extra_deps = []
|
||||||
|
extra_jni_srcs = []
|
||||||
|
|
||||||
|
layer_shell_dep = dependency('gtk4-layer-shell-0', required : false)
|
||||||
|
if layer_shell_dep.found()
|
||||||
|
extra_deps = [ layer_shell_dep ]
|
||||||
|
extra_jni_srcs = [ 'src/api-impl-jni/app/android_app_ATLKeyboardDialog.c' ]
|
||||||
|
add_project_arguments('-DATL_HAS_OSK', language: 'c')
|
||||||
|
endif
|
||||||
|
|
||||||
# libandroid
|
# libandroid
|
||||||
libandroid_so = shared_library('android', [
|
libandroid_so = shared_library('android', [
|
||||||
'src/libandroid/asset_manager.c',
|
'src/libandroid/asset_manager.c',
|
||||||
|
@ -70,6 +80,11 @@ libandroid_so = shared_library('android', [
|
||||||
'-Wl,-z,lazy', # outdated Nvidia driver version 340 lacks EGL symbols
|
'-Wl,-z,lazy', # outdated Nvidia driver version 340 lacks EGL symbols
|
||||||
])
|
])
|
||||||
|
|
||||||
|
wayland_protos_dep = dependency('wayland-protocols', version: '>=1.12')
|
||||||
|
|
||||||
|
# wayland protocols for osk
|
||||||
|
subdir('protocol')
|
||||||
|
|
||||||
libtranslationlayer_so = shared_library('translation_layer_main', [
|
libtranslationlayer_so = shared_library('translation_layer_main', [
|
||||||
'src/api-impl-jni/android_app_NativeActivity.c',
|
'src/api-impl-jni/android_app_NativeActivity.c',
|
||||||
'src/api-impl-jni/android_content_res_AssetManager.c',
|
'src/api-impl-jni/android_content_res_AssetManager.c',
|
||||||
|
@ -85,6 +100,7 @@ libtranslationlayer_so = shared_library('translation_layer_main', [
|
||||||
'src/api-impl-jni/app/android_app_Dialog.c',
|
'src/api-impl-jni/app/android_app_Dialog.c',
|
||||||
'src/api-impl-jni/app/android_app_NotificationManager.c',
|
'src/api-impl-jni/app/android_app_NotificationManager.c',
|
||||||
'src/api-impl-jni/app/android_app_WallpaperManager.c',
|
'src/api-impl-jni/app/android_app_WallpaperManager.c',
|
||||||
|
'src/api-impl-jni/android_inputmethodservice_InputMethodService.c',
|
||||||
'src/api-impl-jni/AssetInputStream.c',
|
'src/api-impl-jni/AssetInputStream.c',
|
||||||
'src/api-impl-jni/audio/android_media_AudioTrack.c',
|
'src/api-impl-jni/audio/android_media_AudioTrack.c',
|
||||||
'src/api-impl-jni/audio/android_media_SoundPool.c',
|
'src/api-impl-jni/audio/android_media_SoundPool.c',
|
||||||
|
@ -138,15 +154,19 @@ libtranslationlayer_so = shared_library('translation_layer_main', [
|
||||||
'src/api-impl-jni/widgets/android_widget_TextView.c',
|
'src/api-impl-jni/widgets/android_widget_TextView.c',
|
||||||
mpris,
|
mpris,
|
||||||
portal_openuri,
|
portal_openuri,
|
||||||
|
wl_proto_headers,
|
||||||
|
wl_proto_sources,
|
||||||
|
extra_jni_srcs,
|
||||||
] + marshal_files,
|
] + marshal_files,
|
||||||
install: true,
|
install: true,
|
||||||
install_dir : get_option('libdir') / 'java/dex/android_translation_layer/natives',
|
install_dir : get_option('libdir') / 'java/dex/android_translation_layer/natives',
|
||||||
install_rpath: '$ORIGIN/:' + get_option('prefix') / get_option('libdir') / 'art',
|
install_rpath: '$ORIGIN/:' + get_option('prefix') / get_option('libdir') / 'art',
|
||||||
dependencies: [
|
dependencies: [
|
||||||
|
extra_deps,
|
||||||
dependency('gtk4', version: '>=4.14'), dependency('gl'), dependency('egl'), dependency('wayland-client'), dependency('jni'),
|
dependency('gtk4', version: '>=4.14'), dependency('gl'), dependency('egl'), dependency('wayland-client'), dependency('jni'),
|
||||||
dependency('libportal'), dependency('sqlite3'), dependency('libavcodec', version: '>=59'), dependency('libdrm'),
|
dependency('libportal'), dependency('sqlite3'), dependency('libavcodec', version: '>=59'), dependency('libdrm'),
|
||||||
dependency('gudev-1.0'), dependency('libswscale'), dependency('webkitgtk-6.0'),
|
dependency('gudev-1.0'), dependency('libswscale'), dependency('webkitgtk-6.0'),
|
||||||
libandroidfw_dep
|
libandroidfw_dep, wayland_protos_dep
|
||||||
],
|
],
|
||||||
link_with: [ libandroid_so ],
|
link_with: [ libandroid_so ],
|
||||||
link_args: [
|
link_args: [
|
||||||
|
|
490
protocol/input-method-unstable-v2.xml
Normal file
490
protocol/input-method-unstable-v2.xml
Normal file
|
@ -0,0 +1,490 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<protocol name="input_method_unstable_v2">
|
||||||
|
|
||||||
|
<copyright>
|
||||||
|
Copyright © 2008-2011 Kristian Høgsberg
|
||||||
|
Copyright © 2010-2011 Intel Corporation
|
||||||
|
Copyright © 2012-2013 Collabora, Ltd.
|
||||||
|
Copyright © 2012, 2013 Intel Corporation
|
||||||
|
Copyright © 2015, 2016 Jan Arne Petersen
|
||||||
|
Copyright © 2017, 2018 Red Hat, Inc.
|
||||||
|
Copyright © 2018 Purism SPC
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice (including the next
|
||||||
|
paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
</copyright>
|
||||||
|
|
||||||
|
<description summary="Protocol for creating input methods">
|
||||||
|
This protocol allows applications to act as input methods for compositors.
|
||||||
|
|
||||||
|
An input method context is used to manage the state of the input method.
|
||||||
|
|
||||||
|
Text strings are UTF-8 encoded, their indices and lengths are in bytes.
|
||||||
|
|
||||||
|
This document adheres to the RFC 2119 when using words like "must",
|
||||||
|
"should", "may", etc.
|
||||||
|
|
||||||
|
Warning! The protocol described in this file is experimental and
|
||||||
|
backward incompatible changes may be made. Backward compatible changes
|
||||||
|
may be added together with the corresponding interface version bump.
|
||||||
|
Backward incompatible changes are done by bumping the version number in
|
||||||
|
the protocol and interface names and resetting the interface version.
|
||||||
|
Once the protocol is to be declared stable, the 'z' prefix and the
|
||||||
|
version number in the protocol and interface names are removed and the
|
||||||
|
interface version number is reset.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<interface name="zwp_input_method_v2" version="1">
|
||||||
|
<description summary="input method">
|
||||||
|
An input method object allows for clients to compose text.
|
||||||
|
|
||||||
|
The objects connects the client to a text input in an application, and
|
||||||
|
lets the client to serve as an input method for a seat.
|
||||||
|
|
||||||
|
The zwp_input_method_v2 object can occupy two distinct states: active and
|
||||||
|
inactive. In the active state, the object is associated to and
|
||||||
|
communicates with a text input. In the inactive state, there is no
|
||||||
|
associated text input, and the only communication is with the compositor.
|
||||||
|
Initially, the input method is in the inactive state.
|
||||||
|
|
||||||
|
Requests issued in the inactive state must be accepted by the compositor.
|
||||||
|
Because of the serial mechanism, and the state reset on activate event,
|
||||||
|
they will not have any effect on the state of the next text input.
|
||||||
|
|
||||||
|
There must be no more than one input method object per seat.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<event name="activate">
|
||||||
|
<description summary="input method has been requested">
|
||||||
|
Notification that a text input focused on this seat requested the input
|
||||||
|
method to be activated.
|
||||||
|
|
||||||
|
This event serves the purpose of providing the compositor with an
|
||||||
|
active input method.
|
||||||
|
|
||||||
|
This event resets all state associated with previous enable, disable,
|
||||||
|
surrounding_text, text_change_cause, and content_type events, as well
|
||||||
|
as the state associated with set_preedit_string, commit_string, and
|
||||||
|
delete_surrounding_text requests. In addition, it marks the
|
||||||
|
zwp_input_method_v2 object as active, and makes any existing
|
||||||
|
zwp_input_popup_surface_v2 objects visible.
|
||||||
|
|
||||||
|
The surrounding_text, and content_type events must follow before the
|
||||||
|
next done event if the text input supports the respective
|
||||||
|
functionality.
|
||||||
|
|
||||||
|
State set with this event is double-buffered. It will get applied on
|
||||||
|
the next zwp_input_method_v2.done event, and stay valid until changed.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="deactivate">
|
||||||
|
<description summary="deactivate event">
|
||||||
|
Notification that no focused text input currently needs an active
|
||||||
|
input method on this seat.
|
||||||
|
|
||||||
|
This event marks the zwp_input_method_v2 object as inactive. The
|
||||||
|
compositor must make all existing zwp_input_popup_surface_v2 objects
|
||||||
|
invisible until the next activate event.
|
||||||
|
|
||||||
|
State set with this event is double-buffered. It will get applied on
|
||||||
|
the next zwp_input_method_v2.done event, and stay valid until changed.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="surrounding_text">
|
||||||
|
<description summary="surrounding text event">
|
||||||
|
Updates the surrounding plain text around the cursor, excluding the
|
||||||
|
preedit text.
|
||||||
|
|
||||||
|
If any preedit text is present, it is replaced with the cursor for the
|
||||||
|
purpose of this event.
|
||||||
|
|
||||||
|
The argument text is a buffer containing the preedit string, and must
|
||||||
|
include the cursor position, and the complete selection. It should
|
||||||
|
contain additional characters before and after these. There is a
|
||||||
|
maximum length of wayland messages, so text can not be longer than 4000
|
||||||
|
bytes.
|
||||||
|
|
||||||
|
cursor is the byte offset of the cursor within the text buffer.
|
||||||
|
|
||||||
|
anchor is the byte offset of the selection anchor within the text
|
||||||
|
buffer. If there is no selected text, anchor must be the same as
|
||||||
|
cursor.
|
||||||
|
|
||||||
|
If this event does not arrive before the first done event, the input
|
||||||
|
method may assume that the text input does not support this
|
||||||
|
functionality and ignore following surrounding_text events.
|
||||||
|
|
||||||
|
Values set with this event are double-buffered. They will get applied
|
||||||
|
and set to initial values on the next zwp_input_method_v2.done
|
||||||
|
event.
|
||||||
|
|
||||||
|
The initial state for affected fields is empty, meaning that the text
|
||||||
|
input does not support sending surrounding text. If the empty values
|
||||||
|
get applied, subsequent attempts to change them may have no effect.
|
||||||
|
</description>
|
||||||
|
<arg name="text" type="string"/>
|
||||||
|
<arg name="cursor" type="uint"/>
|
||||||
|
<arg name="anchor" type="uint"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="text_change_cause">
|
||||||
|
<description summary="indicates the cause of surrounding text change">
|
||||||
|
Tells the input method why the text surrounding the cursor changed.
|
||||||
|
|
||||||
|
Whenever the client detects an external change in text, cursor, or
|
||||||
|
anchor position, it must issue this request to the compositor. This
|
||||||
|
request is intended to give the input method a chance to update the
|
||||||
|
preedit text in an appropriate way, e.g. by removing it when the user
|
||||||
|
starts typing with a keyboard.
|
||||||
|
|
||||||
|
cause describes the source of the change.
|
||||||
|
|
||||||
|
The value set with this event is double-buffered. It will get applied
|
||||||
|
and set to its initial value on the next zwp_input_method_v2.done
|
||||||
|
event.
|
||||||
|
|
||||||
|
The initial value of cause is input_method.
|
||||||
|
</description>
|
||||||
|
<arg name="cause" type="uint" enum="zwp_text_input_v3.change_cause"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="content_type">
|
||||||
|
<description summary="content purpose and hint">
|
||||||
|
Indicates the content type and hint for the current
|
||||||
|
zwp_input_method_v2 instance.
|
||||||
|
|
||||||
|
Values set with this event are double-buffered. They will get applied
|
||||||
|
on the next zwp_input_method_v2.done event.
|
||||||
|
|
||||||
|
The initial value for hint is none, and the initial value for purpose
|
||||||
|
is normal.
|
||||||
|
</description>
|
||||||
|
<arg name="hint" type="uint" enum="zwp_text_input_v3.content_hint"/>
|
||||||
|
<arg name="purpose" type="uint" enum="zwp_text_input_v3.content_purpose"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="done">
|
||||||
|
<description summary="apply state">
|
||||||
|
Atomically applies state changes recently sent to the client.
|
||||||
|
|
||||||
|
The done event establishes and updates the state of the client, and
|
||||||
|
must be issued after any changes to apply them.
|
||||||
|
|
||||||
|
Text input state (content purpose, content hint, surrounding text, and
|
||||||
|
change cause) is conceptually double-buffered within an input method
|
||||||
|
context.
|
||||||
|
|
||||||
|
Events modify the pending state, as opposed to the current state in use
|
||||||
|
by the input method. A done event atomically applies all pending state,
|
||||||
|
replacing the current state. After done, the new pending state is as
|
||||||
|
documented for each related request.
|
||||||
|
|
||||||
|
Events must be applied in the order of arrival.
|
||||||
|
|
||||||
|
Neither current nor pending state are modified unless noted otherwise.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<request name="commit_string">
|
||||||
|
<description summary="commit string">
|
||||||
|
Send the commit string text for insertion to the application.
|
||||||
|
|
||||||
|
Inserts a string at current cursor position (see commit event
|
||||||
|
sequence). The string to commit could be either just a single character
|
||||||
|
after a key press or the result of some composing.
|
||||||
|
|
||||||
|
The argument text is a buffer containing the string to insert. There is
|
||||||
|
a maximum length of wayland messages, so text can not be longer than
|
||||||
|
4000 bytes.
|
||||||
|
|
||||||
|
Values set with this event are double-buffered. They must be applied
|
||||||
|
and reset to initial on the next zwp_text_input_v3.commit request.
|
||||||
|
|
||||||
|
The initial value of text is an empty string.
|
||||||
|
</description>
|
||||||
|
<arg name="text" type="string"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="set_preedit_string">
|
||||||
|
<description summary="pre-edit string">
|
||||||
|
Send the pre-edit string text to the application text input.
|
||||||
|
|
||||||
|
Place a new composing text (pre-edit) at the current cursor position.
|
||||||
|
Any previously set composing text must be removed. Any previously
|
||||||
|
existing selected text must be removed. The cursor is moved to a new
|
||||||
|
position within the preedit string.
|
||||||
|
|
||||||
|
The argument text is a buffer containing the preedit string. There is
|
||||||
|
a maximum length of wayland messages, so text can not be longer than
|
||||||
|
4000 bytes.
|
||||||
|
|
||||||
|
The arguments cursor_begin and cursor_end are counted in bytes relative
|
||||||
|
to the beginning of the submitted string buffer. Cursor should be
|
||||||
|
hidden by the text input when both are equal to -1.
|
||||||
|
|
||||||
|
cursor_begin indicates the beginning of the cursor. cursor_end
|
||||||
|
indicates the end of the cursor. It may be equal or different than
|
||||||
|
cursor_begin.
|
||||||
|
|
||||||
|
Values set with this event are double-buffered. They must be applied on
|
||||||
|
the next zwp_input_method_v2.commit event.
|
||||||
|
|
||||||
|
The initial value of text is an empty string. The initial value of
|
||||||
|
cursor_begin, and cursor_end are both 0.
|
||||||
|
</description>
|
||||||
|
<arg name="text" type="string"/>
|
||||||
|
<arg name="cursor_begin" type="int"/>
|
||||||
|
<arg name="cursor_end" type="int"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="delete_surrounding_text">
|
||||||
|
<description summary="delete text">
|
||||||
|
Remove the surrounding text.
|
||||||
|
|
||||||
|
before_length and after_length are the number of bytes before and after
|
||||||
|
the current cursor index (excluding the preedit text) to delete.
|
||||||
|
|
||||||
|
If any preedit text is present, it is replaced with the cursor for the
|
||||||
|
purpose of this event. In effect before_length is counted from the
|
||||||
|
beginning of preedit text, and after_length from its end (see commit
|
||||||
|
event sequence).
|
||||||
|
|
||||||
|
Values set with this event are double-buffered. They must be applied
|
||||||
|
and reset to initial on the next zwp_input_method_v2.commit request.
|
||||||
|
|
||||||
|
The initial values of both before_length and after_length are 0.
|
||||||
|
</description>
|
||||||
|
<arg name="before_length" type="uint"/>
|
||||||
|
<arg name="after_length" type="uint"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="commit">
|
||||||
|
<description summary="apply state">
|
||||||
|
Apply state changes from commit_string, set_preedit_string and
|
||||||
|
delete_surrounding_text requests.
|
||||||
|
|
||||||
|
The state relating to these events is double-buffered, and each one
|
||||||
|
modifies the pending state. This request replaces the current state
|
||||||
|
with the pending state.
|
||||||
|
|
||||||
|
The connected text input is expected to proceed by evaluating the
|
||||||
|
changes in the following order:
|
||||||
|
|
||||||
|
1. Replace existing preedit string with the cursor.
|
||||||
|
2. Delete requested surrounding text.
|
||||||
|
3. Insert commit string with the cursor at its end.
|
||||||
|
4. Calculate surrounding text to send.
|
||||||
|
5. Insert new preedit text in cursor position.
|
||||||
|
6. Place cursor inside preedit text.
|
||||||
|
|
||||||
|
The serial number reflects the last state of the zwp_input_method_v2
|
||||||
|
object known to the client. The value of the serial argument must be
|
||||||
|
equal to the number of done events already issued by that object. When
|
||||||
|
the compositor receives a commit request with a serial different than
|
||||||
|
the number of past done events, it must proceed as normal, except it
|
||||||
|
should not change the current state of the zwp_input_method_v2 object.
|
||||||
|
</description>
|
||||||
|
<arg name="serial" type="uint"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="get_input_popup_surface">
|
||||||
|
<description summary="create popup surface">
|
||||||
|
Creates a new zwp_input_popup_surface_v2 object wrapping a given
|
||||||
|
surface.
|
||||||
|
|
||||||
|
The surface gets assigned the "input_popup" role. If the surface
|
||||||
|
already has an assigned role, the compositor must issue a protocol
|
||||||
|
error.
|
||||||
|
</description>
|
||||||
|
<arg name="id" type="new_id" interface="zwp_input_popup_surface_v2"/>
|
||||||
|
<arg name="surface" type="object" interface="wl_surface"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="grab_keyboard">
|
||||||
|
<description summary="grab hardware keyboard">
|
||||||
|
Allow an input method to receive hardware keyboard input and process
|
||||||
|
key events to generate text events (with pre-edit) over the wire. This
|
||||||
|
allows input methods which compose multiple key events for inputting
|
||||||
|
text like it is done for CJK languages.
|
||||||
|
|
||||||
|
The compositor should send all keyboard events on the seat to the grab
|
||||||
|
holder via the returned wl_keyboard object. Nevertheless, the
|
||||||
|
compositor may decide not to forward any particular event. The
|
||||||
|
compositor must not further process any event after it has been
|
||||||
|
forwarded to the grab holder.
|
||||||
|
|
||||||
|
Releasing the resulting wl_keyboard object releases the grab.
|
||||||
|
</description>
|
||||||
|
<arg name="keyboard" type="new_id"
|
||||||
|
interface="zwp_input_method_keyboard_grab_v2"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<event name="unavailable">
|
||||||
|
<description summary="input method unavailable">
|
||||||
|
The input method ceased to be available.
|
||||||
|
|
||||||
|
The compositor must issue this event as the only event on the object if
|
||||||
|
there was another input_method object associated with the same seat at
|
||||||
|
the time of its creation.
|
||||||
|
|
||||||
|
The compositor must issue this request when the object is no longer
|
||||||
|
useable, e.g. due to seat removal.
|
||||||
|
|
||||||
|
The input method context becomes inert and should be destroyed after
|
||||||
|
deactivation is handled. Any further requests and events except for the
|
||||||
|
destroy request must be ignored.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor">
|
||||||
|
<description summary="destroy the text input">
|
||||||
|
Destroys the zwp_text_input_v2 object and any associated child
|
||||||
|
objects, i.e. zwp_input_popup_surface_v2 and
|
||||||
|
zwp_input_method_keyboard_grab_v2.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<interface name="zwp_input_popup_surface_v2" version="1">
|
||||||
|
<description summary="popup surface">
|
||||||
|
This interface marks a surface as a popup for interacting with an input
|
||||||
|
method.
|
||||||
|
|
||||||
|
The compositor should place it near the active text input area. It must
|
||||||
|
be visible if and only if the input method is in the active state.
|
||||||
|
|
||||||
|
The client must not destroy the underlying wl_surface while the
|
||||||
|
zwp_input_popup_surface_v2 object exists.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<event name="text_input_rectangle">
|
||||||
|
<description summary="set text input area position">
|
||||||
|
Notify about the position of the area of the text input expressed as a
|
||||||
|
rectangle in surface local coordinates.
|
||||||
|
|
||||||
|
This is a hint to the input method telling it the relative position of
|
||||||
|
the text being entered.
|
||||||
|
</description>
|
||||||
|
<arg name="x" type="int"/>
|
||||||
|
<arg name="y" type="int"/>
|
||||||
|
<arg name="width" type="int"/>
|
||||||
|
<arg name="height" type="int"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor"/>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<interface name="zwp_input_method_keyboard_grab_v2" version="1">
|
||||||
|
<!-- Closely follows wl_keyboard version 6 -->
|
||||||
|
<description summary="keyboard grab">
|
||||||
|
The zwp_input_method_keyboard_grab_v2 interface represents an exclusive
|
||||||
|
grab of the wl_keyboard interface associated with the seat.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<event name="keymap">
|
||||||
|
<description summary="keyboard mapping">
|
||||||
|
This event provides a file descriptor to the client which can be
|
||||||
|
memory-mapped to provide a keyboard mapping description.
|
||||||
|
</description>
|
||||||
|
<arg name="format" type="uint" enum="wl_keyboard.keymap_format"
|
||||||
|
summary="keymap format"/>
|
||||||
|
<arg name="fd" type="fd" summary="keymap file descriptor"/>
|
||||||
|
<arg name="size" type="uint" summary="keymap size, in bytes"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="key">
|
||||||
|
<description summary="key event">
|
||||||
|
A key was pressed or released.
|
||||||
|
The time argument is a timestamp with millisecond granularity, with an
|
||||||
|
undefined base.
|
||||||
|
</description>
|
||||||
|
<arg name="serial" type="uint" summary="serial number of the key event"/>
|
||||||
|
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||||
|
<arg name="key" type="uint" summary="key that produced the event"/>
|
||||||
|
<arg name="state" type="uint" enum="wl_keyboard.key_state"
|
||||||
|
summary="physical state of the key"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="modifiers">
|
||||||
|
<description summary="modifier and group state">
|
||||||
|
Notifies clients that the modifier and/or group state has changed, and
|
||||||
|
it should update its local state.
|
||||||
|
</description>
|
||||||
|
<arg name="serial" type="uint" summary="serial number of the modifiers event"/>
|
||||||
|
<arg name="mods_depressed" type="uint" summary="depressed modifiers"/>
|
||||||
|
<arg name="mods_latched" type="uint" summary="latched modifiers"/>
|
||||||
|
<arg name="mods_locked" type="uint" summary="locked modifiers"/>
|
||||||
|
<arg name="group" type="uint" summary="keyboard layout"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<request name="release" type="destructor">
|
||||||
|
<description summary="release the grab object"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<event name="repeat_info">
|
||||||
|
<description summary="repeat rate and delay">
|
||||||
|
Informs the client about the keyboard's repeat rate and delay.
|
||||||
|
|
||||||
|
This event is sent as soon as the zwp_input_method_keyboard_grab_v2
|
||||||
|
object has been created, and is guaranteed to be received by the
|
||||||
|
client before any key press event.
|
||||||
|
|
||||||
|
Negative values for either rate or delay are illegal. A rate of zero
|
||||||
|
will disable any repeating (regardless of the value of delay).
|
||||||
|
|
||||||
|
This event can be sent later on as well with a new value if necessary,
|
||||||
|
so clients should continue listening for the event past the creation
|
||||||
|
of zwp_input_method_keyboard_grab_v2.
|
||||||
|
</description>
|
||||||
|
<arg name="rate" type="int"
|
||||||
|
summary="the rate of repeating keys in characters per second"/>
|
||||||
|
<arg name="delay" type="int"
|
||||||
|
summary="delay in milliseconds since key down until repeating starts"/>
|
||||||
|
</event>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<interface name="zwp_input_method_manager_v2" version="1">
|
||||||
|
<description summary="input method manager">
|
||||||
|
The input method manager allows the client to become the input method on
|
||||||
|
a chosen seat.
|
||||||
|
|
||||||
|
No more than one input method must be associated with any seat at any
|
||||||
|
given time.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<request name="get_input_method">
|
||||||
|
<description summary="request an input method object">
|
||||||
|
Request a new input zwp_input_method_v2 object associated with a given
|
||||||
|
seat.
|
||||||
|
</description>
|
||||||
|
<arg name="seat" type="object" interface="wl_seat"/>
|
||||||
|
<arg name="input_method" type="new_id" interface="zwp_input_method_v2"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor">
|
||||||
|
<description summary="destroy the input method manager">
|
||||||
|
Destroys the zwp_input_method_manager_v2 object.
|
||||||
|
|
||||||
|
The zwp_input_method_v2 objects originating from it remain valid.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
</protocol>
|
39
protocol/meson.build
Normal file
39
protocol/meson.build
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
fs = import('fs')
|
||||||
|
|
||||||
|
proto_inc = include_directories('.')
|
||||||
|
|
||||||
|
wl_protocol_dir = wayland_protos_dep.get_variable(pkgconfig: 'pkgdatadir')
|
||||||
|
|
||||||
|
wayland_scanner = find_program('wayland-scanner')
|
||||||
|
|
||||||
|
wl_protos = [
|
||||||
|
['input-method-unstable-v2.xml'],
|
||||||
|
['virtual-keyboard-unstable-v1.xml'],
|
||||||
|
]
|
||||||
|
|
||||||
|
wl_proto_sources = []
|
||||||
|
wl_proto_headers = []
|
||||||
|
|
||||||
|
foreach p : wl_protos
|
||||||
|
xml = join_paths(p)
|
||||||
|
|
||||||
|
base = fs.name(xml)
|
||||||
|
proto = fs.stem(base)
|
||||||
|
|
||||||
|
wl_proto_headers += custom_target('@0@ client header'.format(proto),
|
||||||
|
input: xml,
|
||||||
|
output: '@0@-client-protocol.h'.format(proto),
|
||||||
|
command: [wayland_scanner,
|
||||||
|
'client-header',
|
||||||
|
'@INPUT@',
|
||||||
|
'@OUTPUT@']
|
||||||
|
)
|
||||||
|
wl_proto_sources += custom_target('@0@ source'.format(proto),
|
||||||
|
input: xml,
|
||||||
|
output: '@0@-protocol.c'.format(proto),
|
||||||
|
command: [wayland_scanner,
|
||||||
|
'private-code',
|
||||||
|
'@INPUT@',
|
||||||
|
'@OUTPUT@']
|
||||||
|
)
|
||||||
|
endforeach
|
113
protocol/virtual-keyboard-unstable-v1.xml
Normal file
113
protocol/virtual-keyboard-unstable-v1.xml
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<protocol name="virtual_keyboard_unstable_v1">
|
||||||
|
<copyright>
|
||||||
|
Copyright © 2008-2011 Kristian Høgsberg
|
||||||
|
Copyright © 2010-2013 Intel Corporation
|
||||||
|
Copyright © 2012-2013 Collabora, Ltd.
|
||||||
|
Copyright © 2018 Purism SPC
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice (including the next
|
||||||
|
paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
</copyright>
|
||||||
|
|
||||||
|
<interface name="zwp_virtual_keyboard_v1" version="1">
|
||||||
|
<description summary="virtual keyboard">
|
||||||
|
The virtual keyboard provides an application with requests which emulate
|
||||||
|
the behaviour of a physical keyboard.
|
||||||
|
|
||||||
|
This interface can be used by clients on its own to provide raw input
|
||||||
|
events, or it can accompany the input method protocol.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<request name="keymap">
|
||||||
|
<description summary="keyboard mapping">
|
||||||
|
Provide a file descriptor to the compositor which can be
|
||||||
|
memory-mapped to provide a keyboard mapping description.
|
||||||
|
|
||||||
|
Format carries a value from the keymap_format enumeration.
|
||||||
|
</description>
|
||||||
|
<arg name="format" type="uint" summary="keymap format"/>
|
||||||
|
<arg name="fd" type="fd" summary="keymap file descriptor"/>
|
||||||
|
<arg name="size" type="uint" summary="keymap size, in bytes"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<enum name="error">
|
||||||
|
<entry name="no_keymap" value="0" summary="No keymap was set"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<request name="key">
|
||||||
|
<description summary="key event">
|
||||||
|
A key was pressed or released.
|
||||||
|
The time argument is a timestamp with millisecond granularity, with an
|
||||||
|
undefined base. All requests regarding a single object must share the
|
||||||
|
same clock.
|
||||||
|
|
||||||
|
Keymap must be set before issuing this request.
|
||||||
|
|
||||||
|
State carries a value from the key_state enumeration.
|
||||||
|
</description>
|
||||||
|
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||||
|
<arg name="key" type="uint" summary="key that produced the event"/>
|
||||||
|
<arg name="state" type="uint" summary="physical state of the key"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="modifiers">
|
||||||
|
<description summary="modifier and group state">
|
||||||
|
Notifies the compositor that the modifier and/or group state has
|
||||||
|
changed, and it should update state.
|
||||||
|
|
||||||
|
The client should use wl_keyboard.modifiers event to synchronize its
|
||||||
|
internal state with seat state.
|
||||||
|
|
||||||
|
Keymap must be set before issuing this request.
|
||||||
|
</description>
|
||||||
|
<arg name="mods_depressed" type="uint" summary="depressed modifiers"/>
|
||||||
|
<arg name="mods_latched" type="uint" summary="latched modifiers"/>
|
||||||
|
<arg name="mods_locked" type="uint" summary="locked modifiers"/>
|
||||||
|
<arg name="group" type="uint" summary="keyboard layout"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor" since="1">
|
||||||
|
<description summary="destroy the virtual keyboard keyboard object"/>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<interface name="zwp_virtual_keyboard_manager_v1" version="1">
|
||||||
|
<description summary="virtual keyboard manager">
|
||||||
|
A virtual keyboard manager allows an application to provide keyboard
|
||||||
|
input events as if they came from a physical keyboard.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<enum name="error">
|
||||||
|
<entry name="unauthorized" value="0" summary="client not authorized to use the interface"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<request name="create_virtual_keyboard">
|
||||||
|
<description summary="Create a new virtual keyboard">
|
||||||
|
Creates a new virtual keyboard associated to a seat.
|
||||||
|
|
||||||
|
If the compositor enables a keyboard to perform arbitrary actions, it
|
||||||
|
should present an error when an untrusted client requests a new
|
||||||
|
keyboard.
|
||||||
|
</description>
|
||||||
|
<arg name="seat" type="object" interface="wl_seat"/>
|
||||||
|
<arg name="id" type="new_id" interface="zwp_virtual_keyboard_v1"/>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
</protocol>
|
301
src/api-impl-jni/android_inputmethodservice_InputMethodService.c
Normal file
301
src/api-impl-jni/android_inputmethodservice_InputMethodService.c
Normal file
|
@ -0,0 +1,301 @@
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <gdk/wayland/gdkwayland.h>
|
||||||
|
|
||||||
|
#include "input-method-unstable-v2-client-protocol.h"
|
||||||
|
#include "virtual-keyboard-unstable-v1-client-protocol.h"
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "generated_headers/android_inputmethodservice_InputMethodService_ATLInputConnection.h"
|
||||||
|
|
||||||
|
#define INFO(x...) android_log_printf(ANDROID_LOG_INFO, "ATLKeyboardIMS", x)
|
||||||
|
#define DEBUG(fmt, ...) android_log_printf(ANDROID_LOG_DEBUG, "ATLKeyboardIMS", "%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct wl_display *display;
|
||||||
|
struct wl_registry *registry;
|
||||||
|
struct wl_seat *seat;
|
||||||
|
struct zwp_input_method_manager_v2 *input_method_manager;
|
||||||
|
struct zwp_input_method_v2 *input_method;
|
||||||
|
struct zwp_virtual_keyboard_manager_v1 *virtual_keyboard_manager;
|
||||||
|
struct zwp_virtual_keyboard_v1 *virtual_keyboard;
|
||||||
|
|
||||||
|
char compositing[4096];
|
||||||
|
char surrounding[4096];
|
||||||
|
guint text_len;
|
||||||
|
guint cursor;
|
||||||
|
guint serial;
|
||||||
|
} osk = {0};
|
||||||
|
|
||||||
|
/* android_app_ATLKeyboardDialog.c */
|
||||||
|
#ifdef ATL_HAS_OSK
|
||||||
|
extern void atlosk_set_visible(gboolean new_visible);
|
||||||
|
#else
|
||||||
|
static void atlosk_set_visible(gboolean new_visible)
|
||||||
|
{
|
||||||
|
DEBUG("=%d\n", new_visible);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* input-method-unstable-v2
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_activate(void *data,
|
||||||
|
struct zwp_input_method_v2 *zwp_input_method_v2)
|
||||||
|
{
|
||||||
|
atlosk_set_visible(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_deactivate(void *data,
|
||||||
|
struct zwp_input_method_v2 *zwp_input_method_v2)
|
||||||
|
{
|
||||||
|
atlosk_set_visible(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_surrounding_text (void *data,
|
||||||
|
struct zwp_input_method_v2 *zwp_input_method_v2,
|
||||||
|
const char *text,
|
||||||
|
uint32_t cursor,
|
||||||
|
uint32_t anchor)
|
||||||
|
{
|
||||||
|
DEBUG("(cursor=%d, '%s')\n", cursor, text);
|
||||||
|
osk.cursor = cursor;
|
||||||
|
osk.text_len = strnlen(text, sizeof(osk.surrounding));
|
||||||
|
strncpy(osk.surrounding, text, sizeof(osk.surrounding));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_text_change_cause (void *data,
|
||||||
|
struct zwp_input_method_v2 *zwp_input_method_v2,
|
||||||
|
uint32_t cause)
|
||||||
|
{
|
||||||
|
//DEBUG("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_content_type (void *data,
|
||||||
|
struct zwp_input_method_v2 *zwp_input_method_v2,
|
||||||
|
uint32_t hint,
|
||||||
|
uint32_t purpose)
|
||||||
|
{
|
||||||
|
//DEBUG("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_done (void *data,
|
||||||
|
struct zwp_input_method_v2 *zwp_input_method_v2)
|
||||||
|
{
|
||||||
|
osk.serial++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_unavailable (void *data,
|
||||||
|
struct zwp_input_method_v2 *zwp_input_method_v2)
|
||||||
|
{
|
||||||
|
INFO("Input method unavailable");
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct zwp_input_method_v2_listener input_method_listener = {
|
||||||
|
.activate = handle_activate,
|
||||||
|
.deactivate = handle_deactivate,
|
||||||
|
.surrounding_text = handle_surrounding_text,
|
||||||
|
.text_change_cause = handle_text_change_cause,
|
||||||
|
.content_type = handle_content_type,
|
||||||
|
.done = handle_done,
|
||||||
|
.unavailable = handle_unavailable,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
registry_handle_global (void *data,
|
||||||
|
struct wl_registry *registry,
|
||||||
|
uint32_t name,
|
||||||
|
const char *interface,
|
||||||
|
uint32_t version)
|
||||||
|
{
|
||||||
|
if (!strcmp (interface, zwp_input_method_manager_v2_interface.name)) {
|
||||||
|
osk.input_method_manager = wl_registry_bind(registry, name, &zwp_input_method_manager_v2_interface, 1);
|
||||||
|
osk.input_method = zwp_input_method_manager_v2_get_input_method(osk.input_method_manager, osk.seat);
|
||||||
|
zwp_input_method_v2_add_listener (osk.input_method, &input_method_listener, &osk);
|
||||||
|
} else if (!strcmp (interface, zwp_virtual_keyboard_manager_v1_interface.name)) {
|
||||||
|
osk.virtual_keyboard_manager = wl_registry_bind(registry, name, &zwp_virtual_keyboard_manager_v1_interface, 1);
|
||||||
|
osk.virtual_keyboard = zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(osk.virtual_keyboard_manager, osk.seat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
registry_handle_global_remove (void *data,
|
||||||
|
struct wl_registry *registry,
|
||||||
|
uint32_t name)
|
||||||
|
{
|
||||||
|
INFO("Global %d removed but not handled", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_registry_listener registry_listener = {
|
||||||
|
registry_handle_global,
|
||||||
|
registry_handle_global_remove,
|
||||||
|
};
|
||||||
|
|
||||||
|
JNIEXPORT jlong JNICALL Java_android_inputmethodservice_InputMethodService_00024ATLInputConnection_nativeInit
|
||||||
|
(JNIEnv *env, jobject this)
|
||||||
|
{
|
||||||
|
GdkDisplay *gdk_display;
|
||||||
|
GdkSeat *gdk_seat;
|
||||||
|
extern GtkWindow *window; /* Main activity window. */
|
||||||
|
|
||||||
|
INFO("Native init!");
|
||||||
|
|
||||||
|
gdk_display = gtk_root_get_display(GTK_ROOT(window));
|
||||||
|
if (gdk_display == NULL) {
|
||||||
|
g_critical ("ATLKeyboardIMS: Failed to get display: %m\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gdk_seat = gdk_display_get_default_seat(gdk_display);
|
||||||
|
if (gdk_seat == NULL) {
|
||||||
|
g_critical ("ATLKeyboardIMS: Failed to get seat: %m\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
osk.display = gdk_wayland_display_get_wl_display (gdk_display);
|
||||||
|
osk.seat = gdk_wayland_seat_get_wl_seat(gdk_seat);
|
||||||
|
osk.registry = wl_display_get_registry (osk.display);
|
||||||
|
wl_registry_add_listener (osk.registry, ®istry_listener, &osk);
|
||||||
|
|
||||||
|
gtk_widget_set_visible(GTK_WIDGET(window), false);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_android_inputmethodservice_InputMethodService_00024ATLInputConnection_nativeSetCompositingText
|
||||||
|
(JNIEnv *env, jobject this, jlong ptr, jstring text, jint newCursorPosition)
|
||||||
|
{
|
||||||
|
const char *data = (*env)->GetStringUTFChars(env, text, NULL);
|
||||||
|
|
||||||
|
INFO("nativeSetCompositingText('%s', cur=%d)\n", data, newCursorPosition);
|
||||||
|
|
||||||
|
if (osk.input_method) {
|
||||||
|
size_t text_len = strlen(data);
|
||||||
|
int cursor;
|
||||||
|
|
||||||
|
if (newCursorPosition > 0)
|
||||||
|
cursor = text_len - newCursorPosition + 1;
|
||||||
|
else
|
||||||
|
cursor = -1 * newCursorPosition;
|
||||||
|
|
||||||
|
zwp_input_method_v2_set_preedit_string (osk.input_method, data, cursor, cursor);
|
||||||
|
strncpy(osk.compositing, data, sizeof(osk.compositing));
|
||||||
|
zwp_input_method_v2_commit (osk.input_method, osk.serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_android_inputmethodservice_InputMethodService_00024ATLInputConnection_nativeSetCompositingRegion
|
||||||
|
(JNIEnv *env, jobject this, jlong ptr, jint start, jint end)
|
||||||
|
{
|
||||||
|
INFO("nativeSetCompositingRegion(start=%d, end=%d)\n", start, end);
|
||||||
|
|
||||||
|
if (osk.input_method) {
|
||||||
|
int beforeLength, afterLength, cursor = osk.cursor;
|
||||||
|
char tmp[4096] = {0};
|
||||||
|
|
||||||
|
if (start > end) {
|
||||||
|
int tmp = end;
|
||||||
|
end = start;
|
||||||
|
start = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeLength = (end-start);
|
||||||
|
afterLength = 0;
|
||||||
|
|
||||||
|
strncpy(tmp, &osk.surrounding[cursor - beforeLength], beforeLength);
|
||||||
|
cursor = strlen(tmp);
|
||||||
|
|
||||||
|
zwp_input_method_v2_delete_surrounding_text (osk.input_method, beforeLength, afterLength);
|
||||||
|
zwp_input_method_v2_set_preedit_string (osk.input_method, tmp, cursor, cursor);
|
||||||
|
zwp_input_method_v2_commit (osk.input_method, osk.serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_android_inputmethodservice_InputMethodService_00024ATLInputConnection_nativeFinishComposingText
|
||||||
|
(JNIEnv *env, jobject this, jlong ptr)
|
||||||
|
{
|
||||||
|
INFO("nativeFinishCompositingText()\n");
|
||||||
|
|
||||||
|
if (osk.input_method) {
|
||||||
|
zwp_input_method_v2_commit_string (osk.input_method, osk.compositing);
|
||||||
|
zwp_input_method_v2_commit (osk.input_method, osk.serial);
|
||||||
|
osk.compositing[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_android_inputmethodservice_InputMethodService_00024ATLInputConnection_nativeCommitText
|
||||||
|
(JNIEnv *env, jobject this, jlong ptr, jstring text, jint newCursorPosition)
|
||||||
|
{
|
||||||
|
const char *data = (*env)->GetStringUTFChars(env, text, NULL);
|
||||||
|
|
||||||
|
INFO("nativeCommitText('%s', cur=%d)\n", data, newCursorPosition);
|
||||||
|
|
||||||
|
if (osk.input_method) {
|
||||||
|
zwp_input_method_v2_commit_string (osk.input_method, data);
|
||||||
|
zwp_input_method_v2_commit (osk.input_method, osk.serial);
|
||||||
|
osk.compositing[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_android_inputmethodservice_InputMethodService_00024ATLInputConnection_nativeDeleteSurroundingText
|
||||||
|
(JNIEnv *env, jobject this, jlong ptr, jint beforeLength, jint afterLength)
|
||||||
|
{
|
||||||
|
INFO("nativeDeleteSurroundingText(before=%d, after=%d)\n", beforeLength, afterLength);
|
||||||
|
|
||||||
|
if (osk.input_method) {
|
||||||
|
zwp_input_method_v2_delete_surrounding_text (osk.input_method, beforeLength, afterLength);
|
||||||
|
osk.cursor -= beforeLength;
|
||||||
|
zwp_input_method_v2_commit (osk.input_method, osk.serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_android_inputmethodservice_InputMethodService_00024ATLInputConnection_nativeSetSelection
|
||||||
|
(JNIEnv *env, jobject this, jlong ptr, jint start, jint end)
|
||||||
|
{
|
||||||
|
INFO("nativeSetSelection(start=%d, end=%d)\n", start, end);
|
||||||
|
|
||||||
|
if (osk.input_method) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_android_inputmethodservice_InputMethodService_00024ATLInputConnection_nativeSendKeyEvent
|
||||||
|
(JNIEnv *env, jobject this, jlong ptr, jlong time, jlong key, jlong state)
|
||||||
|
{
|
||||||
|
INFO("nativeSendKeyEvent(time=%ld, key=%ld, state=%ld)\n", ptr, time, key, state);
|
||||||
|
|
||||||
|
if (key == 67 /* KEYCODE_DEL */ && state == 1 /* ACTION_UP */) {
|
||||||
|
if (osk.input_method) {
|
||||||
|
zwp_input_method_v2_delete_surrounding_text (osk.input_method, 1, 0);
|
||||||
|
zwp_input_method_v2_commit (osk.input_method, osk.serial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
183
src/api-impl-jni/app/android_app_ATLKeyboardDialog.c
Normal file
183
src/api-impl-jni/app/android_app_ATLKeyboardDialog.c
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <gtk4-layer-shell/gtk4-layer-shell.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "../defines.h"
|
||||||
|
#include "../util.h"
|
||||||
|
#include "../generated_headers/android_app_ATLKeyboardDialog.h"
|
||||||
|
|
||||||
|
#define DEBUG(fmt, ...) android_log_printf(ANDROID_LOG_INFO, "ATLKeyboardDialog", "%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
static GDBusNodeInfo *introspection_data = NULL;
|
||||||
|
static GDBusConnection *dbus_connection = NULL;
|
||||||
|
static gboolean visible = TRUE;
|
||||||
|
static GtkWidget *osk_window = NULL;
|
||||||
|
|
||||||
|
static void emit_property_changed(GDBusConnection *connection)
|
||||||
|
{
|
||||||
|
GVariantBuilder builder;
|
||||||
|
|
||||||
|
g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
|
||||||
|
g_variant_builder_add(&builder, "{sv}", "Visible", g_variant_new_boolean(visible));
|
||||||
|
|
||||||
|
g_dbus_connection_emit_signal(connection,
|
||||||
|
NULL,
|
||||||
|
"/sm/puri/OSK0",
|
||||||
|
"org.freedesktop.DBus.Properties",
|
||||||
|
"PropertiesChanged",
|
||||||
|
g_variant_new("(sa{sv}as)", "sm.puri.OSK0", &builder, NULL), NULL);
|
||||||
|
|
||||||
|
g_variant_builder_clear(&builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Used in IMS. */
|
||||||
|
void atlosk_set_visible(gboolean new_visible)
|
||||||
|
{
|
||||||
|
visible = new_visible;
|
||||||
|
|
||||||
|
if (osk_window) {
|
||||||
|
gtk_widget_set_visible(osk_window, visible);
|
||||||
|
if (dbus_connection)
|
||||||
|
emit_property_changed(dbus_connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_method_call(GDBusConnection *connection,
|
||||||
|
const gchar *sender,
|
||||||
|
const gchar *object_path,
|
||||||
|
const gchar *interface_name,
|
||||||
|
const gchar *method_name,
|
||||||
|
GVariant *parameters,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
if (g_strcmp0(method_name, "SetVisible") == 0) {
|
||||||
|
gboolean new_visible;
|
||||||
|
|
||||||
|
g_variant_get(parameters, "(b)", &new_visible);
|
||||||
|
atlosk_set_visible(new_visible);
|
||||||
|
g_dbus_method_invocation_return_value(invocation, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GVariant *handle_get_property(GDBusConnection *connection,
|
||||||
|
const gchar *sender,
|
||||||
|
const gchar *object_path,
|
||||||
|
const gchar *interface_name,
|
||||||
|
const gchar *property_name,
|
||||||
|
GError **error,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
if (g_strcmp0(property_name, "Visible") == 0) {
|
||||||
|
return g_variant_new_boolean(visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const GDBusInterfaceVTable interface_vtable = {
|
||||||
|
handle_method_call,
|
||||||
|
handle_get_property,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void on_name_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
|
||||||
|
{
|
||||||
|
DEBUG("Acquired D-Bus name: %s\n", name);
|
||||||
|
dbus_connection = connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int connect_osk_dbus_iface(GtkWidget *dialog)
|
||||||
|
{
|
||||||
|
GDBusConnection *connection;
|
||||||
|
GError *error = NULL;
|
||||||
|
guint registration_id;
|
||||||
|
guint owner_id;
|
||||||
|
|
||||||
|
owner_id = g_bus_own_name(G_BUS_TYPE_SESSION,
|
||||||
|
"sm.puri.OSK0",
|
||||||
|
G_BUS_NAME_OWNER_FLAGS_REPLACE,
|
||||||
|
NULL,
|
||||||
|
on_name_acquired,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
|
||||||
|
if (owner_id == 0) {
|
||||||
|
g_printerr("OSK: Error: Could not acquire D-Bus name\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* https://world.pages.gitlab.gnome.org/Phosh/phosh/phosh-dbus-sm.puri.OSK0.html */
|
||||||
|
const gchar introspection_xml[] =
|
||||||
|
"<node>"
|
||||||
|
" <interface name='sm.puri.OSK0'>"
|
||||||
|
" <method name='SetVisible'>"
|
||||||
|
" <arg type='b' name='visible' direction='in'/>"
|
||||||
|
" </method>"
|
||||||
|
" <property name='Visible' type='b' access='read'/>"
|
||||||
|
" </interface>"
|
||||||
|
"</node>";
|
||||||
|
|
||||||
|
introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, &error);
|
||||||
|
if (!introspection_data) {
|
||||||
|
g_printerr("OSK: Failed to parse introspection XML: %s\n", error->message);
|
||||||
|
g_error_free(error);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
|
||||||
|
if (!connection) {
|
||||||
|
g_printerr("OSK: Failed to connect to D-Bus: %s\n", error->message);
|
||||||
|
g_error_free(error);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
registration_id = g_dbus_connection_register_object(connection,
|
||||||
|
"/sm/puri/OSK0",
|
||||||
|
introspection_data->interfaces[0],
|
||||||
|
&interface_vtable,
|
||||||
|
NULL, NULL, &error);
|
||||||
|
if (!registration_id) {
|
||||||
|
g_printerr("OSK: Failed to register object: %s\n", error->message);
|
||||||
|
g_error_free(error);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
osk_window = dialog;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean on_close_request(GtkWidget *dialog, jobject jobj)
|
||||||
|
{
|
||||||
|
JNIEnv *env = get_jni_env();
|
||||||
|
jmethodID dismiss = _METHOD(_CLASS(jobj), "dismiss", "()V");
|
||||||
|
(*env)->CallVoidMethod(env, jobj, dismiss);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jlong JNICALL Java_android_app_ATLKeyboardDialog_nativeInit(JNIEnv *env, jobject this)
|
||||||
|
{
|
||||||
|
GtkWidget *dialog = gtk_window_new();
|
||||||
|
GtkWindow *window = GTK_WINDOW(dialog);
|
||||||
|
|
||||||
|
gtk_layer_init_for_window(window);
|
||||||
|
gtk_layer_auto_exclusive_zone_enable(window);
|
||||||
|
gtk_layer_set_namespace(window, "osk");
|
||||||
|
gtk_layer_set_exclusive_zone(window, 200);
|
||||||
|
|
||||||
|
static const gboolean anchors[] = {TRUE, TRUE, FALSE, TRUE};
|
||||||
|
for (int i = 0; i < GTK_LAYER_SHELL_EDGE_ENTRY_NUMBER; i++)
|
||||||
|
gtk_layer_set_anchor(window, i, anchors[i]);
|
||||||
|
|
||||||
|
connect_osk_dbus_iface(dialog);
|
||||||
|
|
||||||
|
gtk_window_set_child(GTK_WINDOW(dialog), gtk_box_new(GTK_ORIENTATION_VERTICAL, 1));
|
||||||
|
g_signal_connect_swapped(dialog, "response", G_CALLBACK(gtk_window_destroy), dialog);
|
||||||
|
g_signal_connect(GTK_WINDOW(dialog), "close-request", G_CALLBACK(on_close_request), _REF(this));
|
||||||
|
|
||||||
|
return _INTPTR(g_object_ref(dialog));
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||||
|
#include <jni.h>
|
||||||
|
/* Header for class android_app_ATLKeyboardDialog */
|
||||||
|
|
||||||
|
#ifndef _Included_android_app_ATLKeyboardDialog
|
||||||
|
#define _Included_android_app_ATLKeyboardDialog
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Class: android_app_ATLKeyboardDialog
|
||||||
|
* Method: nativeInit
|
||||||
|
* Signature: ()J
|
||||||
|
*/
|
||||||
|
JNIEXPORT jlong JNICALL Java_android_app_ATLKeyboardDialog_nativeInit
|
||||||
|
(JNIEnv *, jobject);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
|
@ -453,14 +453,6 @@ JNIEXPORT void JNICALL Java_android_view_MotionEvent_nativeGetPointerProperties
|
||||||
JNIEXPORT void JNICALL Java_android_view_MotionEvent_nativeScale
|
JNIEXPORT void JNICALL Java_android_view_MotionEvent_nativeScale
|
||||||
(JNIEnv *, jclass, jint, jfloat);
|
(JNIEnv *, jclass, jint, jfloat);
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: android_view_MotionEvent
|
|
||||||
* Method: nativeTransform
|
|
||||||
* Signature: (ILandroid/graphics/Matrix;)V
|
|
||||||
*/
|
|
||||||
JNIEXPORT void JNICALL Java_android_view_MotionEvent_nativeTransform
|
|
||||||
(JNIEnv *, jclass, jint, jobject);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
12
src/api-impl/android/app/ATLKeyboardDialog.java
Normal file
12
src/api-impl/android/app/ATLKeyboardDialog.java
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package android.app;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
public class ATLKeyboardDialog extends Dialog {
|
||||||
|
@Override
|
||||||
|
protected native long nativeInit();
|
||||||
|
|
||||||
|
public ATLKeyboardDialog(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,7 +15,7 @@ import android.view.Window;
|
||||||
public class Dialog implements Window.Callback, DialogInterface {
|
public class Dialog implements Window.Callback, DialogInterface {
|
||||||
protected long nativePtr;
|
protected long nativePtr;
|
||||||
|
|
||||||
private native long nativeInit();
|
protected native long nativeInit();
|
||||||
private native void nativeSetTitle(long ptr, String title);
|
private native void nativeSetTitle(long ptr, String title);
|
||||||
private native void nativeSetContentView(long ptr, long widget);
|
private native void nativeSetContentView(long ptr, long widget);
|
||||||
private native void nativeShow(long ptr);
|
private native void nativeShow(long ptr);
|
||||||
|
|
|
@ -29,6 +29,11 @@ public class ATLKeyboardViewer extends Activity {
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ims.launch_keyboard();
|
boolean is_layershell = true;
|
||||||
|
|
||||||
|
if (extras.containsKey("layershell") && extras.getString("layershell").equals("off"))
|
||||||
|
is_layershell = false;
|
||||||
|
|
||||||
|
ims.launch_keyboard(is_layershell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package android.inputmethodservice;
|
package android.inputmethodservice;
|
||||||
|
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.app.ATLKeyboardDialog;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
@ -30,38 +32,58 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||||
private Dialog kb_dialog;
|
private Dialog kb_dialog;
|
||||||
|
|
||||||
class ATLInputConnection extends BaseInputConnection {
|
class ATLInputConnection extends BaseInputConnection {
|
||||||
|
protected long nativePtr;
|
||||||
|
|
||||||
|
private native long nativeInit();
|
||||||
|
private native boolean nativeSetCompositingText(long ptr, String text, int newCursorPosition);
|
||||||
|
private native boolean nativeSetCompositingRegion(long ptr, int start, int end);
|
||||||
|
private native boolean nativeFinishComposingText(long ptr);
|
||||||
|
private native boolean nativeCommitText(long ptr, String text, int newCursorPosition);
|
||||||
|
private native boolean nativeDeleteSurroundingText(long ptr, int beforeLength, int afterLength);
|
||||||
|
private native boolean nativeSetSelection(long ptr, int start, int end);
|
||||||
|
private native boolean nativeSendKeyEvent(long ptr, long time, long key, long state);
|
||||||
|
|
||||||
|
|
||||||
ATLInputConnection() {
|
ATLInputConnection() {
|
||||||
super(null, false);
|
super(null, false);
|
||||||
|
nativePtr = nativeInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setComposingText(CharSequence text, int newCursorPosition) {
|
public boolean setComposingText(CharSequence text, int newCursorPosition) {
|
||||||
System.out.println("softkeyboard preview: setComposingText(\""+text+"\", "+newCursorPosition+")");
|
return nativeSetCompositingText(nativePtr, text.toString(), newCursorPosition);
|
||||||
return true;
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setComposingRegion(int start, int end) {
|
||||||
|
return nativeSetCompositingRegion(nativePtr, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean finishComposingText() {
|
public boolean finishComposingText() {
|
||||||
System.out.println("softkeyboard preview: finishComposingText()");
|
return nativeFinishComposingText(nativePtr);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean commitText(CharSequence text, int newCursorPosition) {
|
public boolean commitText(CharSequence text, int newCursorPosition) {
|
||||||
System.out.println("softkeyboard preview: commitText(\""+text+"\", "+newCursorPosition+")");
|
return nativeCommitText(nativePtr, text.toString(), newCursorPosition);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
|
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
|
||||||
System.out.println("softkeyboard preview: deleteSurroundingText("+beforeLength+", "+afterLength+")");
|
System.out.println("ATLKeyboardIMS: deleteSurroundingText("+ beforeLength + ", " + afterLength +")");
|
||||||
return true;
|
return nativeDeleteSurroundingText(nativePtr, beforeLength, afterLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setSelection(int start, int end) {
|
||||||
|
return nativeSetSelection(nativePtr, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sendKeyEvent(KeyEvent event) {
|
public boolean sendKeyEvent(KeyEvent event) {
|
||||||
System.out.println("softkeyboard preview: sendKeyEvent("+event+")");
|
System.out.println("softkeyboard preview: sendKeyEvent("+event+")");
|
||||||
return true;
|
return nativeSendKeyEvent(nativePtr, event.getEventTime(), event.getKeyCode(), event.getAction());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* these functions are noop on AOSP by default, so we just add a print for debugging purposes and still return false */
|
/* these functions are noop on AOSP by default, so we just add a print for debugging purposes and still return false */
|
||||||
|
@ -84,8 +106,11 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||||
super(new Context());
|
super(new Context());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void launch_keyboard() {
|
public void launch_keyboard(boolean is_layershell) {
|
||||||
kb_dialog = new Dialog(this);
|
if (is_layershell)
|
||||||
|
kb_dialog = new ATLKeyboardDialog(this);
|
||||||
|
else
|
||||||
|
kb_dialog = new Dialog(this);
|
||||||
|
|
||||||
View decorview = kb_dialog.getWindow().getDecorView();
|
View decorview = kb_dialog.getWindow().getDecorView();
|
||||||
decorview.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
|
decorview.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
|
||||||
|
@ -138,7 +163,7 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputBinding getCurrentInputBinding() {
|
public InputBinding getCurrentInputBinding() {
|
||||||
return new InputBinding(new ATLInputConnection(), null, 0, 0);
|
return new InputBinding(input_connection, null, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IBinder onBind(Intent intent) {
|
public IBinder onBind(Intent intent) {
|
||||||
|
|
|
@ -1363,7 +1363,8 @@ public final class MotionEvent extends InputEvent {
|
||||||
int pointerIndex, PointerProperties outPointerProperties);
|
int pointerIndex, PointerProperties outPointerProperties);
|
||||||
|
|
||||||
private static native void nativeScale(int nativePtr, float scale);
|
private static native void nativeScale(int nativePtr, float scale);
|
||||||
private static native void nativeTransform(int nativePtr, Matrix matrix);
|
private static /* native */ void nativeTransform(int nativePtr, Matrix matrix) {
|
||||||
|
}
|
||||||
|
|
||||||
private static final int X_OFFSET = 0;
|
private static final int X_OFFSET = 0;
|
||||||
private static final int Y_OFFSET = 1;
|
private static final int Y_OFFSET = 1;
|
||||||
|
|
|
@ -37,6 +37,7 @@ srcs = [
|
||||||
'android/app/ApplicationErrorReport.java',
|
'android/app/ApplicationErrorReport.java',
|
||||||
'android/app/ApplicationExitInfo.java',
|
'android/app/ApplicationExitInfo.java',
|
||||||
'android/app/Dialog.java',
|
'android/app/Dialog.java',
|
||||||
|
'android/app/ATLKeyboardDialog.java',
|
||||||
'android/app/DownloadManager.java',
|
'android/app/DownloadManager.java',
|
||||||
'android/app/Fragment.java',
|
'android/app/Fragment.java',
|
||||||
'android/app/FragmentManager.java',
|
'android/app/FragmentManager.java',
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue