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
96c5a68e10
commit
45adfeda91
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',
|
||||
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_so = shared_library('android', [
|
||||
'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
|
||||
])
|
||||
|
||||
wayland_protos_dep = dependency('wayland-protocols', version: '>=1.12')
|
||||
|
||||
# wayland protocols for osk
|
||||
subdir('protocol')
|
||||
|
||||
libtranslationlayer_so = shared_library('translation_layer_main', [
|
||||
'src/api-impl-jni/android_app_NativeActivity.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_NotificationManager.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/audio/android_media_AudioTrack.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',
|
||||
mpris,
|
||||
portal_openuri,
|
||||
wl_proto_headers,
|
||||
wl_proto_sources,
|
||||
extra_jni_srcs,
|
||||
] + marshal_files,
|
||||
install: true,
|
||||
install_dir : get_option('libdir') / 'java/dex/android_translation_layer/natives',
|
||||
install_rpath: '$ORIGIN/:' + get_option('prefix') / get_option('libdir') / 'art',
|
||||
dependencies: [
|
||||
extra_deps,
|
||||
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('gudev-1.0'), dependency('libswscale'), dependency('webkitgtk-6.0'),
|
||||
libandroidfw_dep
|
||||
libandroidfw_dep, wayland_protos_dep
|
||||
],
|
||||
link_with: [ libandroid_so ],
|
||||
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
|
||||
(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
|
||||
}
|
||||
#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 {
|
||||
protected long nativePtr;
|
||||
|
||||
private native long nativeInit();
|
||||
protected native long nativeInit();
|
||||
private native void nativeSetTitle(long ptr, String title);
|
||||
private native void nativeSetContentView(long ptr, long widget);
|
||||
private native void nativeShow(long ptr);
|
||||
|
|
|
@ -29,6 +29,11 @@ public class ATLKeyboardViewer extends Activity {
|
|||
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;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.ATLKeyboardDialog;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
@ -30,38 +32,58 @@ public class InputMethodService extends AbstractInputMethodService {
|
|||
private Dialog kb_dialog;
|
||||
|
||||
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() {
|
||||
super(null, false);
|
||||
nativePtr = nativeInit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setComposingText(CharSequence text, int newCursorPosition) {
|
||||
System.out.println("softkeyboard preview: setComposingText(\""+text+"\", "+newCursorPosition+")");
|
||||
return true;
|
||||
return nativeSetCompositingText(nativePtr, text.toString(), newCursorPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setComposingRegion(int start, int end) {
|
||||
return nativeSetCompositingRegion(nativePtr, start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean finishComposingText() {
|
||||
System.out.println("softkeyboard preview: finishComposingText()");
|
||||
return true;
|
||||
return nativeFinishComposingText(nativePtr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean commitText(CharSequence text, int newCursorPosition) {
|
||||
System.out.println("softkeyboard preview: commitText(\""+text+"\", "+newCursorPosition+")");
|
||||
return true;
|
||||
return nativeCommitText(nativePtr, text.toString(), newCursorPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
|
||||
System.out.println("softkeyboard preview: deleteSurroundingText("+beforeLength+", "+afterLength+")");
|
||||
return true;
|
||||
System.out.println("ATLKeyboardIMS: deleteSurroundingText("+ beforeLength + ", " + afterLength +")");
|
||||
return nativeDeleteSurroundingText(nativePtr, beforeLength, afterLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setSelection(int start, int end) {
|
||||
return nativeSetSelection(nativePtr, start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendKeyEvent(KeyEvent 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 */
|
||||
|
@ -84,8 +106,11 @@ public class InputMethodService extends AbstractInputMethodService {
|
|||
super(new Context());
|
||||
}
|
||||
|
||||
public void launch_keyboard() {
|
||||
kb_dialog = new Dialog(this);
|
||||
public void launch_keyboard(boolean is_layershell) {
|
||||
if (is_layershell)
|
||||
kb_dialog = new ATLKeyboardDialog(this);
|
||||
else
|
||||
kb_dialog = new Dialog(this);
|
||||
|
||||
View decorview = kb_dialog.getWindow().getDecorView();
|
||||
decorview.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
|
||||
|
@ -138,7 +163,7 @@ public class InputMethodService extends AbstractInputMethodService {
|
|||
}
|
||||
|
||||
public InputBinding getCurrentInputBinding() {
|
||||
return new InputBinding(new ATLInputConnection(), null, 0, 0);
|
||||
return new InputBinding(input_connection, null, 0, 0);
|
||||
}
|
||||
|
||||
public IBinder onBind(Intent intent) {
|
||||
|
|
|
@ -1363,7 +1363,8 @@ public final class MotionEvent extends InputEvent {
|
|||
int pointerIndex, PointerProperties outPointerProperties);
|
||||
|
||||
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 Y_OFFSET = 1;
|
||||
|
|
|
@ -37,6 +37,7 @@ srcs = [
|
|||
'android/app/ApplicationErrorReport.java',
|
||||
'android/app/ApplicationExitInfo.java',
|
||||
'android/app/Dialog.java',
|
||||
'android/app/ATLKeyboardDialog.java',
|
||||
'android/app/DownloadManager.java',
|
||||
'android/app/Fragment.java',
|
||||
'android/app/FragmentManager.java',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue