Fix text-input support for new API
Update text input support to upstream text-input protocol v2 from wayland-protocols. Remove support for input-method protocol for now. Map text-input protocol on compositor side to the Qt input method API, this allows to use any qt platform input method on compositor side (especially qtvirtualkeyboard). Add support for qtvirtualkeyboard to pure-qml example. Implement all missing functions of the text-input protocol. Change-Id: I597451ff65454a63dff86026b6a8d1ffbe07ce02 Done-with: Zeno Endemann <zeno.endemann@kdab.com> Reviewed-by: Giulio Camuffo <giulio.camuffo@kdab.com>
This commit is contained in:
parent
17d8de6ca3
commit
853f8f6b67
273
src/3rdparty/wayland/protocols/input-method.xml
vendored
273
src/3rdparty/wayland/protocols/input-method.xml
vendored
@ -1,273 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="input_method">
|
||||
<copyright>
|
||||
Copyright © 2012, 2013 Intel Corporation
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that copyright notice and this permission
|
||||
notice appear in supporting documentation, and that the name of
|
||||
the copyright holders not be used in advertising or publicity
|
||||
pertaining to distribution of the software without specific,
|
||||
written prior permission. The copyright holders make no
|
||||
representations about the suitability of this software for any
|
||||
purpose. It is provided "as is" without express or implied
|
||||
warranty.
|
||||
|
||||
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
|
||||
<interface name="wl_input_method_context" version="1">
|
||||
<description summary="input method context">
|
||||
Corresponds to a text model on input method side. An input method context
|
||||
is created on text mode activation on the input method side. It allows to
|
||||
receive information about the text model from the application via events.
|
||||
Input method contexts do not keep state after deactivation and should be
|
||||
destroyed after deactivation is handled.
|
||||
|
||||
Text is generally UTF-8 encoded, indices and lengths are in bytes.
|
||||
|
||||
Serials are used to synchronize the state between the text input and
|
||||
an input method. New serials are sent by the text input in the
|
||||
commit_state request and are used by the input method to indicate
|
||||
the known text input state in events like preedit_string, commit_string,
|
||||
and keysym. The text input can then ignore events from the input method
|
||||
which are based on an outdated state (for example after a reset).
|
||||
</description>
|
||||
<request name="destroy" type="destructor"/>
|
||||
<request name="commit_string">
|
||||
<description summary="commit string">
|
||||
Send the commit string text for insertion to the application.
|
||||
|
||||
The text to commit could be either just a single character after a key
|
||||
press or the result of some composing (pre-edit). It could be also an
|
||||
empty text when some text should be removed (see
|
||||
delete_surrounding_text) or when the input cursor should be moved (see
|
||||
cursor_position).
|
||||
|
||||
Any previously set composing text will be removed.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial of the latest known text input state"/>
|
||||
<arg name="text" type="string"/>
|
||||
</request>
|
||||
<request name="preedit_string">
|
||||
<description summary="pre-edit string">
|
||||
Send the pre-edit string text to the application text input.
|
||||
|
||||
The commit text can be used to replace the preedit text on reset (for
|
||||
example on unfocus).
|
||||
|
||||
Also previously sent preedit_style and preedit_cursor requests are
|
||||
processed bt the text_input also.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial of the latest known text input state"/>
|
||||
<arg name="text" type="string"/>
|
||||
<arg name="commit" type="string"/>
|
||||
</request>
|
||||
<request name="preedit_styling">
|
||||
<description summary="pre-edit styling">
|
||||
Sets styling information on composing text. The style is applied for
|
||||
length in bytes from index relative to the beginning of
|
||||
the composing text (as byte offset). Multiple styles can
|
||||
be applied to a composing text.
|
||||
|
||||
This request should be sent before sending preedit_string request.
|
||||
</description>
|
||||
<arg name="index" type="uint"/>
|
||||
<arg name="length" type="uint"/>
|
||||
<arg name="style" type="uint"/>
|
||||
</request>
|
||||
<request name="preedit_cursor">
|
||||
<description summary="pre-edit cursor">
|
||||
Sets the cursor position inside the composing text (as byte offset)
|
||||
relative to the start of the composing text.
|
||||
|
||||
When index is negative no cursor should be displayed.
|
||||
|
||||
This request should be sent before sending preedit_string request.
|
||||
</description>
|
||||
<arg name="index" type="int"/>
|
||||
</request>
|
||||
<request name="delete_surrounding_text">
|
||||
<description summary="delete text">
|
||||
|
||||
|
||||
This request will be handled on text_input side as part of a directly
|
||||
following commit_string request.
|
||||
</description>
|
||||
<arg name="index" type="int"/>
|
||||
<arg name="length" type="uint"/>
|
||||
</request>
|
||||
<request name="cursor_position">
|
||||
<description summary="set cursor to a new position">
|
||||
Sets the cursor and anchor to a new position. Index is the new cursor
|
||||
position in bytess (when >= 0 relative to the end of inserted text
|
||||
else relative to beginning of inserted text). Anchor is the new anchor
|
||||
position in bytes (when >= 0 relative to the end of inserted text, else
|
||||
relative to beginning of inserted text). When there should be no
|
||||
selected text anchor should be the same as index.
|
||||
|
||||
This request will be handled on text_input side as part of a directly
|
||||
following commit_string request.
|
||||
</description>
|
||||
<arg name="index" type="int"/>
|
||||
<arg name="anchor" type="int"/>
|
||||
</request>
|
||||
<request name="modifiers_map">
|
||||
<arg name="map" type="array"/>
|
||||
</request>
|
||||
<request name="keysym">
|
||||
<description summary="keysym">
|
||||
Notify when a key event was sent. Key events should not be used for
|
||||
normal text input operations, which should be done with commit_string,
|
||||
delete_surrounfing_text, etc. The key event follows the wl_keyboard key
|
||||
event convention. Sym is a XKB keysym, state a wl_keyboard key_state.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial of the latest known text input state"/>
|
||||
<arg name="time" type="uint"/>
|
||||
<arg name="sym" type="uint"/>
|
||||
<arg name="state" type="uint"/>
|
||||
<arg name="modifiers" type="uint"/>
|
||||
</request>
|
||||
<request name="grab_keyboard">
|
||||
<description summary="grab hardware keyboard">
|
||||
Allows 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.
|
||||
</description>
|
||||
<arg name="keyboard" type="new_id" interface="wl_keyboard"/>
|
||||
</request>
|
||||
<request name="key">
|
||||
<description summary="forward key event">
|
||||
Should be used when filtering key events with grab_keyboard.
|
||||
|
||||
When the wl_keyboard::key event is not processed by the input
|
||||
method itself and should be sent to the client instead, forward it
|
||||
with this request. The arguments should be the ones from the
|
||||
wl_keyboard::key event.
|
||||
|
||||
For generating custom key events use the keysym request instead.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial from wl_keyboard::key"/>
|
||||
<arg name="time" type="uint" summary="time from wl_keyboard::key"/>
|
||||
<arg name="key" type="uint" summary="key from wl_keyboard::key"/>
|
||||
<arg name="state" type="uint" summary="state from wl_keyboard::key"/>
|
||||
</request>
|
||||
<request name="modifiers">
|
||||
<description summary="forward modifiers event">
|
||||
Should be used when filtering key events with grab_keyboard.
|
||||
|
||||
When the wl_keyboard::modifiers event should be also send to the
|
||||
client, forward it with this request. The arguments should be the ones
|
||||
from the wl_keyboard::modifiers event.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial from wl_keyboard::modifiers"/>
|
||||
<arg name="mods_depressed" type="uint" summary="mods_depressed from wl_keyboard::modifiers"/>
|
||||
<arg name="mods_latched" type="uint" summary="mods_latched from wl_keyboard::modifiers"/>
|
||||
<arg name="mods_locked" type="uint" summary="mods_locked from wl_keyboard::modifiers"/>
|
||||
<arg name="group" type="uint" summary="group from wl_keyboard::modifiers"/>
|
||||
</request>
|
||||
<request name="language">
|
||||
<arg name="serial" type="uint" summary="serial of the latest known text input state"/>
|
||||
<arg name="language" type="string"/>
|
||||
</request>
|
||||
<request name="text_direction">
|
||||
<arg name="serial" type="uint" summary="serial of the latest known text input state"/>
|
||||
<arg name="direction" type="uint"/>
|
||||
</request>
|
||||
<event name="surrounding_text">
|
||||
<description summary="surrounding text event">
|
||||
The plain surrounding text around the input position. Cursor is the
|
||||
position in bytes within the surrounding text relative to the beginning
|
||||
of the text. Anchor is the position in bytes of the selection anchor
|
||||
within the surrounding text relative to the beginning of the text. If
|
||||
there is no selected text anchor is the same as cursor.
|
||||
</description>
|
||||
<arg name="text" type="string"/>
|
||||
<arg name="cursor" type="uint"/>
|
||||
<arg name="anchor" type="uint"/>
|
||||
</event>
|
||||
<event name="reset">
|
||||
</event>
|
||||
<event name="content_type">
|
||||
<arg name="hint" type="uint"/>
|
||||
<arg name="purpose" type="uint"/>
|
||||
</event>
|
||||
<event name="invoke_action">
|
||||
<arg name="button" type="uint"/>
|
||||
<arg name="index" type="uint"/>
|
||||
</event>
|
||||
<event name="commit_state">
|
||||
<arg name="serial" type="uint" summary="serial of text input state"/>
|
||||
</event>
|
||||
<event name="preferred_language">
|
||||
<arg name="language" type="string"/>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="wl_input_method" version="1">
|
||||
<description summary="input method">
|
||||
An input method object is responsible to compose text in response to
|
||||
input from hardware or virtual keyboards. There is one input method
|
||||
object per seat. On activate there is a new input method context object
|
||||
created which allows the input method to communicate with the text model.
|
||||
</description>
|
||||
<event name="activate">
|
||||
<description summary="activate event">
|
||||
A text model was activated. Creates an input method context object
|
||||
which allows communication with the text model.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="wl_input_method_context"/>
|
||||
</event>
|
||||
<event name="deactivate">
|
||||
<description summary="activate event">
|
||||
The text model corresponding to the context argument was deactivated.
|
||||
The input method context should be destroyed after deactivation is
|
||||
handled.
|
||||
</description>
|
||||
<arg name="context" type="object" interface="wl_input_method_context"/>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="wl_input_panel" version="1">
|
||||
<description summary="interface for implementing keyboards">
|
||||
Only one client can bind this interface at a time.
|
||||
</description>
|
||||
|
||||
<request name="get_input_panel_surface">
|
||||
<arg name="id" type="new_id" interface="wl_input_panel_surface"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="wl_input_panel_surface" version="1">
|
||||
<enum name="position">
|
||||
<entry name="center_bottom" value="0"/>
|
||||
</enum>
|
||||
|
||||
<request name="set_toplevel">
|
||||
<description summary="set the surface type as a keyboard">
|
||||
A keybaord surface is only shown, when a text model is active
|
||||
</description>
|
||||
<arg name="output" type="object" interface="wl_output"/>
|
||||
<arg name="position" type="uint"/>
|
||||
</request>
|
||||
|
||||
<request name="set_overlay_panel">
|
||||
<description summary="set the surface type as an overlay panel">
|
||||
An overlay panel is shown near the input cursor above the application
|
||||
window when a text model is active.
|
||||
</description>
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
478
src/3rdparty/wayland/protocols/text-input-unstable-v2.xml
vendored
Normal file
478
src/3rdparty/wayland/protocols/text-input-unstable-v2.xml
vendored
Normal file
@ -0,0 +1,478 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<protocol name="text_input_unstable_v2">
|
||||
<copyright>
|
||||
Copyright © 2012, 2013 Intel Corporation
|
||||
Copyright © 2015, 2016 Jan Arne Petersen
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that copyright notice and this permission
|
||||
notice appear in supporting documentation, and that the name of
|
||||
the copyright holders not be used in advertising or publicity
|
||||
pertaining to distribution of the software without specific,
|
||||
written prior permission. The copyright holders make no
|
||||
representations about the suitability of this software for any
|
||||
purpose. It is provided "as is" without express or implied
|
||||
warranty.
|
||||
|
||||
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<interface name="zwp_text_input_v2" version="1">
|
||||
<description summary="text input">
|
||||
The zwp_text_input_v2 interface represents text input and input methods
|
||||
associated with a seat. It provides enter/leave events to follow the
|
||||
text input focus for a seat.
|
||||
|
||||
Requests are used to enable/disable the text-input object and set
|
||||
state information like surrounding and selected text or the content type.
|
||||
The information about the entered text is sent to the text-input object
|
||||
via the pre-edit and commit events. Using this interface removes the need
|
||||
for applications to directly process hardware key events and compose text
|
||||
out of them.
|
||||
|
||||
Text is valid UTF-8 encoded, indices and lengths are in bytes. Indices
|
||||
have to always point to the first byte of an UTF-8 encoded code point.
|
||||
Lengths are not allowed to contain just a part of an UTF-8 encoded code
|
||||
point.
|
||||
|
||||
State is sent by the state requests (set_surrounding_text,
|
||||
set_content_type, set_cursor_rectangle and set_preferred_language) and
|
||||
an update_state request. After an enter or an input_method_change event
|
||||
all state information is invalidated and needs to be resent from the
|
||||
client. A reset or entering a new widget on client side also
|
||||
invalidates all current state information.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="Destroy the wp_text_input">
|
||||
Destroy the wp_text_input object. Also disables all surfaces enabled
|
||||
through this wp_text_input object
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="enable">
|
||||
<description summary="enable text input for surface">
|
||||
Enable text input in a surface (usually when a text entry inside of it
|
||||
has focus).
|
||||
|
||||
This can be called before or after a surface gets text (or keyboard)
|
||||
focus via the enter event. Text input to a surface is only active
|
||||
when it has the current text (or keyboard) focus and is enabled.
|
||||
</description>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
</request>
|
||||
|
||||
<request name="disable">
|
||||
<description summary="disable text input for surface">
|
||||
Disable text input in a surface (typically when there is no focus on any
|
||||
text entry inside the surface).
|
||||
</description>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
</request>
|
||||
|
||||
<request name="show_input_panel">
|
||||
<description summary="show input panels">
|
||||
Requests input panels (virtual keyboard) to show.
|
||||
|
||||
This should be used for example to show a virtual keyboard again
|
||||
(with a tap) after it was closed by pressing on a close button on the
|
||||
keyboard.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="hide_input_panel">
|
||||
<description summary="hide input panels">
|
||||
Requests input panels (virtual keyboard) to hide.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="set_surrounding_text">
|
||||
<description summary="sets the surrounding text">
|
||||
Sets the plain surrounding text around the input position. Text is
|
||||
UTF-8 encoded. Cursor is the byte offset within the surrounding text.
|
||||
Anchor is the byte offset of the selection anchor within the
|
||||
surrounding text. If there is no selected text, anchor is the same as
|
||||
cursor.
|
||||
|
||||
Make sure to always send some text before and after the cursor
|
||||
except when the cursor is at the beginning or end of text.
|
||||
|
||||
When there was a configure_surrounding_text event take the
|
||||
before_cursor and after_cursor arguments into account for picking how
|
||||
much surrounding text to send.
|
||||
|
||||
There is a maximum length of wayland messages so text can not be
|
||||
longer than 4000 bytes.
|
||||
</description>
|
||||
<arg name="text" type="string"/>
|
||||
<arg name="cursor" type="int"/>
|
||||
<arg name="anchor" type="int"/>
|
||||
</request>
|
||||
|
||||
<enum name="content_hint" bitfield="true">
|
||||
<description summary="content hint">
|
||||
Content hint is a bitmask to allow to modify the behavior of the text
|
||||
input.
|
||||
</description>
|
||||
<entry name="none" value="0x0" summary="no special behaviour"/>
|
||||
<entry name="auto_completion" value="0x1" summary="suggest word completions"/>
|
||||
<entry name="auto_correction" value="0x2" summary="suggest word corrections"/>
|
||||
<entry name="auto_capitalization" value="0x4" summary="switch to uppercase letters at the start of a sentence"/>
|
||||
<entry name="lowercase" value="0x8" summary="prefer lowercase letters"/>
|
||||
<entry name="uppercase" value="0x10" summary="prefer uppercase letters"/>
|
||||
<entry name="titlecase" value="0x20" summary="prefer casing for titles and headings (can be language dependent)"/>
|
||||
<entry name="hidden_text" value="0x40" summary="characters should be hidden"/>
|
||||
<entry name="sensitive_data" value="0x80" summary="typed text should not be stored"/>
|
||||
<entry name="latin" value="0x100" summary="just latin characters should be entered"/>
|
||||
<entry name="multiline" value="0x200" summary="the text input is multiline"/>
|
||||
</enum>
|
||||
|
||||
<enum name="content_purpose">
|
||||
<description summary="content purpose">
|
||||
The content purpose allows to specify the primary purpose of a text
|
||||
input.
|
||||
|
||||
This allows an input method to show special purpose input panels with
|
||||
extra characters or to disallow some characters.
|
||||
</description>
|
||||
<entry name="normal" value="0" summary="default input, allowing all characters"/>
|
||||
<entry name="alpha" value="1" summary="allow only alphabetic characters"/>
|
||||
<entry name="digits" value="2" summary="allow only digits"/>
|
||||
<entry name="number" value="3" summary="input a number (including decimal separator and sign)"/>
|
||||
<entry name="phone" value="4" summary="input a phone number"/>
|
||||
<entry name="url" value="5" summary="input an URL"/>
|
||||
<entry name="email" value="6" summary="input an email address"/>
|
||||
<entry name="name" value="7" summary="input a name of a person"/>
|
||||
<entry name="password" value="8" summary="input a password (combine with password or sensitive_data hint)"/>
|
||||
<entry name="date" value="9" summary="input a date"/>
|
||||
<entry name="time" value="10" summary="input a time"/>
|
||||
<entry name="datetime" value="11" summary="input a date and time"/>
|
||||
<entry name="terminal" value="12" summary="input for a terminal"/>
|
||||
</enum>
|
||||
|
||||
<request name="set_content_type">
|
||||
<description summary="set content purpose and hint">
|
||||
Sets the content purpose and content hint. While the purpose is the
|
||||
basic purpose of an input field, the hint flags allow to modify some
|
||||
of the behavior.
|
||||
|
||||
When no content type is explicitly set, a normal content purpose with
|
||||
none hint should be assumed.
|
||||
</description>
|
||||
<arg name="hint" type="uint" enum="content_hint"/>
|
||||
<arg name="purpose" type="uint" enum="content_purpose"/>
|
||||
</request>
|
||||
|
||||
<request name="set_cursor_rectangle">
|
||||
<description summary="set cursor position">
|
||||
Sets the cursor outline as a x, y, width, height rectangle in surface
|
||||
local coordinates.
|
||||
|
||||
Allows the compositor to put a window with word suggestions near the
|
||||
cursor.
|
||||
</description>
|
||||
<arg name="x" type="int"/>
|
||||
<arg name="y" type="int"/>
|
||||
<arg name="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
</request>
|
||||
|
||||
<request name="set_preferred_language">
|
||||
<description summary="sets preferred language">
|
||||
Sets a specific language. This allows for example a virtual keyboard to
|
||||
show a language specific layout. The "language" argument is a RFC-3066
|
||||
format language tag.
|
||||
|
||||
It could be used for example in a word processor to indicate language of
|
||||
currently edited document or in an instant message application which
|
||||
tracks languages of contacts.
|
||||
</description>
|
||||
<arg name="language" type="string"/>
|
||||
</request>
|
||||
|
||||
<enum name="update_state">
|
||||
<description summary="update_state flags">
|
||||
Defines the reason for sending an updated state.
|
||||
</description>
|
||||
<entry name="change" value="0" summary="updated state because it changed"/>
|
||||
<entry name="full" value="1" summary="full state after enter or input_method_changed event"/>
|
||||
<entry name="reset" value="2" summary="full state after reset"/>
|
||||
<entry name="enter" value="3" summary="full state after switching focus to a different widget on client side"/>
|
||||
</enum>
|
||||
|
||||
<request name="update_state">
|
||||
<description summary="update state">
|
||||
Allows to atomically send state updates from client.
|
||||
|
||||
This request should follow after a batch of state updating requests
|
||||
like set_surrounding_text, set_content_type, set_cursor_rectangle and
|
||||
set_preferred_language.
|
||||
|
||||
The flags field indicates why an updated state is sent to the input
|
||||
method.
|
||||
|
||||
Reset should be used by an editor widget after the text was changed
|
||||
outside of the normal input method flow.
|
||||
|
||||
For "change" it is enough to send the changed state, else the full
|
||||
state should be send.
|
||||
|
||||
Serial should be set to the serial from the last enter or
|
||||
input_method_changed event.
|
||||
|
||||
To make sure to not receive outdated input method events after a
|
||||
reset or switching to a new widget wl_display_sync() should be used
|
||||
after update_state in these cases.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial of the enter or input_method_changed event"/>
|
||||
<arg name="reason" type="uint" enum="update_state"/>
|
||||
</request>
|
||||
|
||||
<event name="enter">
|
||||
<description summary="enter event">
|
||||
Notification that this seat's text-input focus is on a certain surface.
|
||||
|
||||
When the seat has the keyboard capability the text-input focus follows
|
||||
the keyboard focus.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial to be used by update_state"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
</event>
|
||||
|
||||
<event name="leave">
|
||||
<description summary="leave event">
|
||||
Notification that this seat's text-input focus is no longer on
|
||||
a certain surface.
|
||||
|
||||
The leave notification is sent before the enter notification
|
||||
for the new focus.
|
||||
|
||||
When the seat has the keyboard capabillity the text-input focus follows
|
||||
the keyboard focus.
|
||||
</description>
|
||||
<arg name="serial" type="uint"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
</event>
|
||||
|
||||
<enum name="input_panel_visibility">
|
||||
<entry name="hidden" value="0"
|
||||
summary="the input panel (virtual keyboard) is hidden"/>
|
||||
<entry name="visible" value="1"
|
||||
summary="the input panel (virtual keyboard) is visible"/>
|
||||
</enum>
|
||||
|
||||
<event name="input_panel_state">
|
||||
<description summary="state of the input panel">
|
||||
Notification that the visibility of the input panel (virtual keyboard)
|
||||
changed.
|
||||
|
||||
The rectangle x, y, width, height defines the area overlapped by the
|
||||
input panel (virtual keyboard) on the surface having the text
|
||||
focus in surface local coordinates.
|
||||
|
||||
That can be used to make sure widgets are visible and not covered by
|
||||
a virtual keyboard.
|
||||
</description>
|
||||
<arg name="state" type="uint" enum="input_panel_visibility"/>
|
||||
<arg name="x" type="int"/>
|
||||
<arg name="y" type="int"/>
|
||||
<arg name="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
</event>
|
||||
|
||||
<event name="preedit_string">
|
||||
<description summary="pre-edit">
|
||||
Notify when a new composing text (pre-edit) should be set around the
|
||||
current cursor position. Any previously set composing text should
|
||||
be removed.
|
||||
|
||||
The commit text can be used to replace the composing text in some cases
|
||||
(for example when losing focus).
|
||||
|
||||
The text input should also handle all preedit_style and preedit_cursor
|
||||
events occurring directly before preedit_string.
|
||||
</description>
|
||||
<arg name="text" type="string"/>
|
||||
<arg name="commit" type="string"/>
|
||||
</event>
|
||||
|
||||
<enum name="preedit_style">
|
||||
<entry name="default" value="0" summary="default style for composing text"/>
|
||||
<entry name="none" value="1" summary="composing text should be shown the same as non-composing text"/>
|
||||
<entry name="active" value="2" summary="composing text might be bold"/>
|
||||
<entry name="inactive" value="3" summary="composing text might be cursive"/>
|
||||
<entry name="highlight" value="4" summary="composing text might have a different background color"/>
|
||||
<entry name="underline" value="5" summary="composing text might be underlined"/>
|
||||
<entry name="selection" value="6" summary="composing text should be shown the same as selected text"/>
|
||||
<entry name="incorrect" value="7" summary="composing text might be underlined with a red wavy line"/>
|
||||
</enum>
|
||||
|
||||
<event name="preedit_styling">
|
||||
<description summary="pre-edit styling">
|
||||
Sets styling information on composing text. The style is applied for
|
||||
length bytes from index relative to the beginning of the composing
|
||||
text (as byte offset). Multiple styles can be applied to a composing
|
||||
text by sending multiple preedit_styling events.
|
||||
|
||||
This event is handled as part of a following preedit_string event.
|
||||
</description>
|
||||
<arg name="index" type="uint"/>
|
||||
<arg name="length" type="uint"/>
|
||||
<arg name="style" type="uint" enum="preedit_style"/>
|
||||
</event>
|
||||
|
||||
<event name="preedit_cursor">
|
||||
<description summary="pre-edit cursor">
|
||||
Sets the cursor position inside the composing text (as byte
|
||||
offset) relative to the start of the composing text. When index is a
|
||||
negative number no cursor is shown.
|
||||
|
||||
When no preedit_cursor event is sent the cursor will be at the end of
|
||||
the composing text by default.
|
||||
|
||||
This event is handled as part of a following preedit_string event.
|
||||
</description>
|
||||
<arg name="index" type="int"/>
|
||||
</event>
|
||||
|
||||
<event name="commit_string">
|
||||
<description summary="commit">
|
||||
Notify when text should be inserted into the editor widget. The text to
|
||||
commit could be either just a single character after a key press or the
|
||||
result of some composing (pre-edit). It could be also an empty text
|
||||
when some text should be removed (see delete_surrounding_text) or when
|
||||
the input cursor should be moved (see cursor_position).
|
||||
|
||||
Any previously set composing text should be removed.
|
||||
</description>
|
||||
<arg name="text" type="string"/>
|
||||
</event>
|
||||
|
||||
<event name="cursor_position">
|
||||
<description summary="set cursor to new position">
|
||||
Notify when the cursor or anchor position should be modified.
|
||||
|
||||
This event should be handled as part of a following commit_string
|
||||
event.
|
||||
|
||||
The text between anchor and index should be selected.
|
||||
</description>
|
||||
<arg name="index" type="int" summary="position of cursor"/>
|
||||
<arg name="anchor" type="int" summary="position of selection anchor"/>
|
||||
</event>
|
||||
|
||||
<event name="delete_surrounding_text">
|
||||
<description summary="delete surrounding text">
|
||||
Notify when the text around the current cursor position should be
|
||||
deleted. BeforeLength and afterLength is the length (in bytes) of text
|
||||
before and after the current cursor position (excluding the selection)
|
||||
to delete.
|
||||
|
||||
This event should be handled as part of a following commit_string
|
||||
or preedit_string event.
|
||||
</description>
|
||||
<arg name="before_length" type="uint" summary="length of text before current cursor positon"/>
|
||||
<arg name="after_length" type="uint" summary="length of text after current cursor positon"/>
|
||||
</event>
|
||||
|
||||
<event name="modifiers_map">
|
||||
<description summary="modifiers map">
|
||||
Transfer an array of 0-terminated modifiers names. The position in
|
||||
the array is the index of the modifier as used in the modifiers
|
||||
bitmask in the keysym event.
|
||||
</description>
|
||||
<arg name="map" type="array"/>
|
||||
</event>
|
||||
|
||||
<event name="keysym">
|
||||
<description summary="keysym">
|
||||
Notify when a key event was sent. Key events should not be used
|
||||
for normal text input operations, which should be done with
|
||||
commit_string, delete_surrounding_text, etc. The key event follows
|
||||
the wl_keyboard key event convention. Sym is a XKB keysym, state a
|
||||
wl_keyboard key_state. Modifiers are a mask for effective modifiers
|
||||
(where the modifier indices are set by the modifiers_map event)
|
||||
</description>
|
||||
<arg name="time" type="uint"/>
|
||||
<arg name="sym" type="uint"/>
|
||||
<arg name="state" type="uint"/>
|
||||
<arg name="modifiers" type="uint"/>
|
||||
</event>
|
||||
|
||||
<event name="language">
|
||||
<description summary="language">
|
||||
Sets the language of the input text. The "language" argument is a RFC-3066
|
||||
format language tag.
|
||||
</description>
|
||||
<arg name="language" type="string"/>
|
||||
</event>
|
||||
|
||||
<enum name="text_direction">
|
||||
<entry name="auto" value="0" summary="automatic text direction based on text and language"/>
|
||||
<entry name="ltr" value="1" summary="left-to-right"/>
|
||||
<entry name="rtl" value="2" summary="right-to-left"/>
|
||||
</enum>
|
||||
|
||||
<event name="text_direction">
|
||||
<description summary="text direction">
|
||||
Sets the text direction of input text.
|
||||
|
||||
It is mainly needed for showing input cursor on correct side of the
|
||||
editor when there is no input yet done and making sure neutral
|
||||
direction text is laid out properly.
|
||||
</description>
|
||||
<arg name="direction" type="uint" enum="text_direction"/>
|
||||
</event>
|
||||
|
||||
<event name="configure_surrounding_text">
|
||||
<description summary="configure amount of surrounding text to be sent">
|
||||
Configure what amount of surrounding text is expected by the
|
||||
input method. The surrounding text will be sent in the
|
||||
set_surrounding_text request on the following state information updates.
|
||||
</description>
|
||||
<arg name="before_cursor" type="int"/>
|
||||
<arg name="after_cursor" type="int"/>
|
||||
</event>
|
||||
|
||||
<event name="input_method_changed">
|
||||
<description summary="Notifies about a changed input method">
|
||||
The input method changed on compositor side, which invalidates all
|
||||
current state information. New state information should be sent from
|
||||
the client via state requests (set_surrounding_text,
|
||||
set_content_hint, ...) and update_state.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial to be used by update_state"/>
|
||||
<arg name="flags" type="uint" summary="currently unused"/>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="zwp_text_input_manager_v2" version="1">
|
||||
<description summary="text input manager">
|
||||
A factory for text-input objects. This object is a global singleton.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="Destroy the wp_text_input_manager">
|
||||
Destroy the wp_text_input_manager object.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="get_text_input">
|
||||
<description summary="create a new text input object">
|
||||
Creates a new text-input object for a given seat.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="zwp_text_input_v2"/>
|
||||
<arg name="seat" type="object" interface="wl_seat"/>
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
346
src/3rdparty/wayland/protocols/text.xml
vendored
346
src/3rdparty/wayland/protocols/text.xml
vendored
@ -1,346 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="text">
|
||||
|
||||
<copyright>
|
||||
Copyright © 2012, 2013 Intel Corporation
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that copyright notice and this permission
|
||||
notice appear in supporting documentation, and that the name of
|
||||
the copyright holders not be used in advertising or publicity
|
||||
pertaining to distribution of the software without specific,
|
||||
written prior permission. The copyright holders make no
|
||||
representations about the suitability of this software for any
|
||||
purpose. It is provided "as is" without express or implied
|
||||
warranty.
|
||||
|
||||
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<interface name="wl_text_input" version="1">
|
||||
<description summary="text input">
|
||||
An object used for text input. Adds support for text input and input
|
||||
methods to applications. A text-input object is created from a
|
||||
wl_text_input_manager and corresponds typically to a text entry in an
|
||||
application.
|
||||
Requests are used to activate/deactivate the text-input object and set
|
||||
state information like surrounding and selected text or the content type.
|
||||
The information about entered text is sent to the text-input object via
|
||||
the pre-edit and commit events. Using this interface removes the need
|
||||
for applications to directly process hardware key events and compose text
|
||||
out of them.
|
||||
|
||||
Text is generally UTF-8 encoded, indices and lengths are in bytes.
|
||||
|
||||
Serials are used to synchronize the state between the text input and
|
||||
an input method. New serials are sent by the text input in the
|
||||
commit_state request and are used by the input method to indicate
|
||||
the known text input state in events like preedit_string, commit_string,
|
||||
and keysym. The text input can then ignore events from the input method
|
||||
which are based on an outdated state (for example after a reset).
|
||||
</description>
|
||||
<request name="activate">
|
||||
<description summary="request activation">
|
||||
Requests the text-input object to be activated (typically when the
|
||||
text entry gets focus).
|
||||
The seat argument is a wl_seat which maintains the focus for this
|
||||
activation. The surface argument is a wl_surface assigned to the
|
||||
text-input object and tracked for focus lost. The enter event
|
||||
is emitted on successful activation.
|
||||
</description>
|
||||
<arg name="seat" type="object" interface="wl_seat"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
</request>
|
||||
<request name="deactivate">
|
||||
<description summary="request deactivation">
|
||||
Requests the text-input object to be deactivated (typically when the
|
||||
text entry lost focus). The seat argument is a wl_seat which was used
|
||||
for activation.
|
||||
</description>
|
||||
<arg name="seat" type="object" interface="wl_seat"/>
|
||||
</request>
|
||||
<request name="show_input_panel">
|
||||
<description summary="show input panels">
|
||||
Requests input panels (virtual keyboard) to show.
|
||||
</description>
|
||||
</request>
|
||||
<request name="hide_input_panel">
|
||||
<description summary="hide input panels">
|
||||
Requests input panels (virtual keyboard) to hide.
|
||||
</description>
|
||||
</request>
|
||||
<request name="reset">
|
||||
<description summary="reset">
|
||||
Should be called by an editor widget when the input state should be
|
||||
reset, for example after the text was changed outside of the normal
|
||||
input method flow.
|
||||
</description>
|
||||
</request>
|
||||
<request name="set_surrounding_text">
|
||||
<description summary="sets the surrounding text">
|
||||
Sets the plain surrounding text around the input position. Text is
|
||||
UTF-8 encoded. Cursor is the byte offset within the
|
||||
surrounding text. Anchor is the byte offset of the
|
||||
selection anchor within the surrounding text. If there is no selected
|
||||
text anchor is the same as cursor.
|
||||
</description>
|
||||
<arg name="text" type="string"/>
|
||||
<arg name="cursor" type="uint"/>
|
||||
<arg name="anchor" type="uint"/>
|
||||
</request>
|
||||
<enum name="content_hint">
|
||||
<description summary="content hint">
|
||||
Content hint is a bitmask to allow to modify the behavior of the text
|
||||
input.
|
||||
</description>
|
||||
<entry name="none" value="0x0" summary="no special behaviour"/>
|
||||
<entry name="default" value="0x7" summary="auto completion, correction and capitalization"/>
|
||||
<entry name="password" value="0xc0" summary="hidden and sensitive text"/>
|
||||
<entry name="auto_completion" value="0x1" summary="suggest word completions"/>
|
||||
<entry name="auto_correction" value="0x2" summary="suggest word corrections"/>
|
||||
<entry name="auto_capitalization" value="0x4" summary="switch to uppercase letters at the start of a sentence"/>
|
||||
<entry name="lowercase" value="0x8" summary="prefer lowercase letters"/>
|
||||
<entry name="uppercase" value="0x10" summary="prefer uppercase letters"/>
|
||||
<entry name="titlecase" value="0x20" summary="prefer casing for titles and headings (can be language dependent)"/>
|
||||
<entry name="hidden_text" value="0x40" summary="characters should be hidden"/>
|
||||
<entry name="sensitive_data" value="0x80" summary="typed text should not be stored"/>
|
||||
<entry name="latin" value="0x100" summary="just latin characters should be entered"/>
|
||||
<entry name="multiline" value="0x200" summary="the text input is multiline"/>
|
||||
</enum>
|
||||
<enum name="content_purpose">
|
||||
<description summary="content purpose">
|
||||
The content purpose allows to specify the primary purpose of a text
|
||||
input.
|
||||
|
||||
This allows an input method to show special purpose input panels with
|
||||
extra characters or to disallow some characters.
|
||||
</description>
|
||||
<entry name="normal" value="0" summary="default input, allowing all characters"/>
|
||||
<entry name="alpha" value="1" summary="allow only alphabetic characters"/>
|
||||
<entry name="digits" value="2" summary="allow only digits"/>
|
||||
<entry name="number" value="3" summary="input a number (including decimal separator and sign)"/>
|
||||
<entry name="phone" value="4" summary="input a phone number"/>
|
||||
<entry name="url" value="5" summary="input an URL"/>
|
||||
<entry name="email" value="6" summary="input an email address"/>
|
||||
<entry name="name" value="7" summary="input a name of a person"/>
|
||||
<entry name="password" value="8" summary="input a password (combine with password or sensitive_data hint)"/>
|
||||
<entry name="date" value="9" summary="input a date"/>
|
||||
<entry name="time" value="10" summary="input a time"/>
|
||||
<entry name="datetime" value="11" summary="input a date and time"/>
|
||||
<entry name="terminal" value="12" summary="input for a terminal"/>
|
||||
</enum>
|
||||
<request name="set_content_type">
|
||||
<description summary="set content purpose and hint">
|
||||
Sets the content purpose and content hint. While the purpose is the
|
||||
basic purpose of an input field, the hint flags allow to modify some
|
||||
of the behavior.
|
||||
|
||||
When no content type is explicitly set, a normal content purpose with
|
||||
default hints (auto completion, auto correction, auto capitalization)
|
||||
should be assumed.
|
||||
</description>
|
||||
<arg name="hint" type="uint"/>
|
||||
<arg name="purpose" type="uint"/>
|
||||
</request>
|
||||
<request name="set_cursor_rectangle">
|
||||
<arg name="x" type="int"/>
|
||||
<arg name="y" type="int"/>
|
||||
<arg name="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
</request>
|
||||
<request name="set_preferred_language">
|
||||
<description summary="sets preferred language">
|
||||
Sets a specific language. This allows for example a virtual keyboard to
|
||||
show a language specific layout. The "language" argument is a RFC-3066
|
||||
format language tag.
|
||||
|
||||
It could be used for example in a word processor to indicate language of
|
||||
currently edited document or in an instant message application which tracks
|
||||
languages of contacts.
|
||||
</description>
|
||||
<arg name="language" type="string"/>
|
||||
</request>
|
||||
<request name="commit_state">
|
||||
<arg name="serial" type="uint" summary="used to identify the known state"/>
|
||||
</request>
|
||||
<request name="invoke_action">
|
||||
<arg name="button" type="uint"/>
|
||||
<arg name="index" type="uint"/>
|
||||
</request>
|
||||
<event name="enter">
|
||||
<description summary="enter event">
|
||||
Notify the text-input object when it received focus. Typically in
|
||||
response to an activate request.
|
||||
</description>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
</event>
|
||||
<event name="leave">
|
||||
<description summary="leave event">
|
||||
Notify the text-input object when it lost focus. Either in response
|
||||
to a deactivate request or when the assigned surface lost focus or was
|
||||
destroyed.
|
||||
</description>
|
||||
</event>
|
||||
<event name="modifiers_map">
|
||||
<description summary="modifiers map">
|
||||
Transfer an array of 0-terminated modifiers names. The position in
|
||||
the array is the index of the modifier as used in the modifiers
|
||||
bitmask in the keysym event.
|
||||
</description>
|
||||
<arg name="map" type="array"/>
|
||||
</event>
|
||||
<event name="input_panel_state">
|
||||
<description summary="state of the input panel">
|
||||
Notify when the visibility state of the input panel changed.
|
||||
</description>
|
||||
<arg name="state" type="uint"/>
|
||||
</event>
|
||||
<event name="preedit_string">
|
||||
<description summary="pre-edit">
|
||||
Notify when a new composing text (pre-edit) should be set around the
|
||||
current cursor position. Any previously set composing text should
|
||||
be removed.
|
||||
|
||||
The commit text can be used to replace the preedit text on reset
|
||||
(for example on unfocus).
|
||||
|
||||
The text input should also handle all preedit_style and preedit_cursor
|
||||
events occuring directly before preedit_string.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial of the latest known text input state"/>
|
||||
<arg name="text" type="string"/>
|
||||
<arg name="commit" type="string"/>
|
||||
</event>
|
||||
<enum name="preedit_style">
|
||||
<entry name="default" value="0" summary="default style for composing text"/>
|
||||
<entry name="none" value="1" summary="style should be the same as in non-composing text"/>
|
||||
<entry name="active" value="2"/>
|
||||
<entry name="inactive" value="3"/>
|
||||
<entry name="highlight" value="4"/>
|
||||
<entry name="underline" value="5"/>
|
||||
<entry name="selection" value="6"/>
|
||||
<entry name="incorrect" value="7"/>
|
||||
</enum>
|
||||
<event name="preedit_styling">
|
||||
<description summary="pre-edit styling">
|
||||
Sets styling information on composing text. The style is applied for
|
||||
length bytes from index relative to the beginning of the composing
|
||||
text (as byte offset). Multiple styles can
|
||||
be applied to a composing text by sending multiple preedit_styling
|
||||
events.
|
||||
|
||||
This event is handled as part of a following preedit_string event.
|
||||
</description>
|
||||
<arg name="index" type="uint"/>
|
||||
<arg name="length" type="uint"/>
|
||||
<arg name="style" type="uint"/>
|
||||
</event>
|
||||
<event name="preedit_cursor">
|
||||
<description summary="pre-edit cursor">
|
||||
Sets the cursor position inside the composing text (as byte
|
||||
offset) relative to the start of the composing text. When index is a
|
||||
negative number no cursor is shown.
|
||||
|
||||
This event is handled as part of a following preedit_string event.
|
||||
</description>
|
||||
<arg name="index" type="int"/>
|
||||
</event>
|
||||
<event name="commit_string">
|
||||
<description summary="commit">
|
||||
Notify when text should be inserted into the editor widget. The text to
|
||||
commit could be either just a single character after a key press or the
|
||||
result of some composing (pre-edit). It could be also an empty text
|
||||
when some text should be removed (see delete_surrounding_text) or when
|
||||
the input cursor should be moved (see cursor_position).
|
||||
|
||||
Any previously set composing text should be removed.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial of the latest known text input state"/>
|
||||
<arg name="text" type="string"/>
|
||||
</event>
|
||||
<event name="cursor_position">
|
||||
<description summary="set cursor to new position">
|
||||
Notify when the cursor or anchor position should be modified.
|
||||
|
||||
This event should be handled as part of a following commit_string
|
||||
event.
|
||||
</description>
|
||||
<arg name="index" type="int"/>
|
||||
<arg name="anchor" type="int"/>
|
||||
</event>
|
||||
<event name="delete_surrounding_text">
|
||||
<description summary="delete surrounding text">
|
||||
Notify when the text around the current cursor position should be
|
||||
deleted.
|
||||
|
||||
Index is relative to the current cursor (in bytes).
|
||||
Length is the length of deleted text (in bytes).
|
||||
|
||||
This event should be handled as part of a following commit_string
|
||||
event.
|
||||
</description>
|
||||
<arg name="index" type="int"/>
|
||||
<arg name="length" type="uint"/>
|
||||
</event>
|
||||
<event name="keysym">
|
||||
<description summary="keysym">
|
||||
Notify when a key event was sent. Key events should not be used
|
||||
for normal text input operations, which should be done with
|
||||
commit_string, delete_surrounding_text, etc. The key event follows
|
||||
the wl_keyboard key event convention. Sym is a XKB keysym, state a
|
||||
wl_keyboard key_state. Modifiers are a mask for effective modifiers
|
||||
(where the modifier indices are set by the modifiers_map event)
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial of the latest known text input state"/>
|
||||
<arg name="time" type="uint"/>
|
||||
<arg name="sym" type="uint"/>
|
||||
<arg name="state" type="uint"/>
|
||||
<arg name="modifiers" type="uint"/>
|
||||
</event>
|
||||
<event name="language">
|
||||
<description summary="language">
|
||||
Sets the language of the input text. The "language" argument is a RFC-3066
|
||||
format language tag.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial of the latest known text input state"/>
|
||||
<arg name="language" type="string"/>
|
||||
</event>
|
||||
<enum name="text_direction">
|
||||
<entry name="auto" value="0" summary="automatic text direction based on text and language"/>
|
||||
<entry name="ltr" value="1" summary="left-to-right"/>
|
||||
<entry name="rtl" value="2" summary="right-to-left"/>
|
||||
</enum>
|
||||
<event name="text_direction">
|
||||
<description summary="text direction">
|
||||
Sets the text direction of input text.
|
||||
|
||||
It is mainly needed for showing input cursor on correct side of the
|
||||
editor when there is no input yet done and making sure neutral
|
||||
direction text is laid out properly.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial of the latest known text input state"/>
|
||||
<arg name="direction" type="uint"/>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="wl_text_input_manager" version="1">
|
||||
<description summary="text input manager">
|
||||
A factory for text-input objects. This object is a global singleton.
|
||||
</description>
|
||||
<request name="create_text_input">
|
||||
<description summary="create text input">
|
||||
Creates a new text-input object.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="wl_text_input"/>
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
@ -39,7 +39,7 @@ WAYLANDCLIENTSOURCES += \
|
||||
../extensions/touch-extension.xml \
|
||||
../extensions/qtkey-extension.xml \
|
||||
../extensions/windowmanager.xml \
|
||||
../3rdparty/protocol/text.xml \
|
||||
../3rdparty/protocol/text-input-unstable-v2.xml \
|
||||
../3rdparty/protocol/xdg-shell.xml \
|
||||
|
||||
SOURCES += qwaylandintegration.cpp \
|
||||
@ -66,6 +66,7 @@ SOURCES += qwaylandintegration.cpp \
|
||||
qwaylandqtkey.cpp \
|
||||
../shared/qwaylandmimehelper.cpp \
|
||||
../shared/qwaylandxkb.cpp \
|
||||
../shared/qwaylandinputmethodeventbuilder.cpp \
|
||||
qwaylandabstractdecoration.cpp \
|
||||
qwaylanddecorationfactory.cpp \
|
||||
qwaylanddecorationplugin.cpp \
|
||||
@ -100,6 +101,7 @@ HEADERS += qwaylandintegration_p.h \
|
||||
qwaylandqtkey_p.h \
|
||||
../shared/qwaylandmimehelper.h \
|
||||
../shared/qwaylandxkb.h \
|
||||
../shared/qwaylandinputmethodeventbuilder.h \
|
||||
qwaylandabstractdecoration_p.h \
|
||||
qwaylanddecorationfactory_p.h \
|
||||
qwaylanddecorationplugin_p.h \
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "qwaylandxdgshell_p.h"
|
||||
#include "qwaylandxdgsurface_p.h"
|
||||
#include "qwaylandwlshellsurface_p.h"
|
||||
#include "qwaylandinputcontext_p.h"
|
||||
|
||||
#include "qwaylandwindowmanagerintegration_p.h"
|
||||
#include "qwaylandshellintegration_p.h"
|
||||
@ -60,7 +61,7 @@
|
||||
#include "qwaylandtouch_p.h"
|
||||
#include "qwaylandqtkey_p.h"
|
||||
|
||||
#include <QtWaylandClient/private/qwayland-text.h>
|
||||
#include <QtWaylandClient/private/qwayland-text-input-unstable-v2.h>
|
||||
#include <QtWaylandClient/private/qwayland-xdg-shell.h>
|
||||
|
||||
#include <QtCore/QAbstractEventDispatcher>
|
||||
@ -281,8 +282,11 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
|
||||
mTouchExtension.reset(new QWaylandTouchExtension(this, id));
|
||||
} else if (interface == QStringLiteral("qt_key_extension")) {
|
||||
mQtKeyExtension.reset(new QWaylandQtKeyExtension(this, id));
|
||||
} else if (interface == QStringLiteral("wl_text_input_manager")) {
|
||||
mTextInputManager.reset(new QtWayland::wl_text_input_manager(registry, id, 1));
|
||||
} else if (interface == QStringLiteral("zwp_text_input_manager_v2")) {
|
||||
mTextInputManager.reset(new QtWayland::zwp_text_input_manager_v2(registry, id, 1));
|
||||
foreach (QWaylandInputDevice *inputDevice, mInputDevices) {
|
||||
inputDevice->setTextInput(new QWaylandTextInput(this, mTextInputManager->get_text_input(inputDevice->wl_seat())));
|
||||
}
|
||||
} else if (interface == QStringLiteral("qt_hardware_integration")) {
|
||||
mHardwareIntegration.reset(new QWaylandHardwareIntegration(registry, id));
|
||||
// make a roundtrip here since we need to receive the events sent by
|
||||
|
@ -76,7 +76,7 @@ namespace QtWayland {
|
||||
class qt_shell;
|
||||
class qt_sub_surface_extension;
|
||||
class qt_surface_extension;
|
||||
class wl_text_input_manager;
|
||||
class zwp_text_input_manager_v2;
|
||||
class xdg_shell;
|
||||
}
|
||||
|
||||
@ -147,7 +147,7 @@ public:
|
||||
|
||||
QtWayland::qt_surface_extension *windowExtension() const { return mWindowExtension.data(); }
|
||||
QWaylandTouchExtension *touchExtension() const { return mTouchExtension.data(); }
|
||||
QtWayland::wl_text_input_manager *textInputManager() const { return mTextInputManager.data(); }
|
||||
QtWayland::zwp_text_input_manager_v2 *textInputManager() const { return mTextInputManager.data(); }
|
||||
QWaylandHardwareIntegration *hardwareIntegration() const { return mHardwareIntegration.data(); }
|
||||
|
||||
struct RegistryGlobal {
|
||||
@ -207,7 +207,7 @@ private:
|
||||
QScopedPointer<QWaylandTouchExtension> mTouchExtension;
|
||||
QScopedPointer<QWaylandQtKeyExtension> mQtKeyExtension;
|
||||
QScopedPointer<QWaylandWindowManagerIntegration> mWindowManagerIntegration;
|
||||
QScopedPointer<QtWayland::wl_text_input_manager> mTextInputManager;
|
||||
QScopedPointer<QtWayland::zwp_text_input_manager_v2> mTextInputManager;
|
||||
QScopedPointer<QWaylandHardwareIntegration> mHardwareIntegration;
|
||||
QSocketNotifier *mReadNotifier;
|
||||
int mFd;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Klarälvdalens Datakonsult AB (KDAB).
|
||||
** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtWaylandClient module of the Qt Toolkit.
|
||||
@ -40,147 +40,358 @@
|
||||
|
||||
#include "qwaylandinputcontext_p.h"
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QWindow>
|
||||
#ifndef QT_NO_WAYLAND_XKB
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#endif
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QTextCharFormat>
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/private/qguiapplication_p.h>
|
||||
#include <QtGui/qpa/qplatformintegration.h>
|
||||
|
||||
#include "qwaylanddisplay_p.h"
|
||||
#include "qwaylandinputdevice_p.h"
|
||||
#include "qwaylandinputmethodeventbuilder.h"
|
||||
#include "qwaylandwindow_p.h"
|
||||
#include "qwaylandxkb.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_LOGGING_CATEGORY(qLcQpaInputMethods, "qt.qpa.input.methods")
|
||||
|
||||
namespace QtWaylandClient {
|
||||
|
||||
static Qt::Key toQtKey(uint32_t sym)
|
||||
{
|
||||
#ifndef QT_NO_WAYLAND_XKB
|
||||
switch (static_cast<xkb_keysym_t>(sym)) {
|
||||
case XKB_KEY_BackSpace:
|
||||
return Qt::Key_Backspace;
|
||||
case XKB_KEY_Return:
|
||||
return Qt::Key_Return;
|
||||
case XKB_KEY_Left:
|
||||
return Qt::Key_Left;
|
||||
case XKB_KEY_Up:
|
||||
return Qt::Key_Up;
|
||||
case XKB_KEY_Right:
|
||||
return Qt::Key_Right;
|
||||
case XKB_KEY_Down:
|
||||
return Qt::Key_Down;
|
||||
default:
|
||||
return Qt::Key_unknown;
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(sym)
|
||||
return Qt::Key_unknown;
|
||||
#endif
|
||||
namespace {
|
||||
const Qt::InputMethodQueries supportedQueries = Qt::ImEnabled |
|
||||
Qt::ImSurroundingText |
|
||||
Qt::ImCursorPosition |
|
||||
Qt::ImAnchorPosition |
|
||||
Qt::ImHints |
|
||||
Qt::ImCursorRectangle |
|
||||
Qt::ImPreferredLanguage;
|
||||
}
|
||||
|
||||
static QEvent::Type toQEventType(uint32_t state)
|
||||
{
|
||||
switch (static_cast<wl_keyboard_key_state>(state)) {
|
||||
default:
|
||||
case WL_KEYBOARD_KEY_STATE_PRESSED:
|
||||
return QEvent::KeyPress;
|
||||
case WL_KEYBOARD_KEY_STATE_RELEASED:
|
||||
return QEvent::KeyRelease;
|
||||
}
|
||||
}
|
||||
|
||||
QWaylandTextInput::QWaylandTextInput(struct ::wl_text_input *text_input)
|
||||
: QtWayland::wl_text_input(text_input)
|
||||
, m_commit()
|
||||
QWaylandTextInput::QWaylandTextInput(QWaylandDisplay *display, struct ::zwp_text_input_v2 *text_input)
|
||||
: QtWayland::zwp_text_input_v2(text_input)
|
||||
, m_display(display)
|
||||
, m_builder()
|
||||
, m_serial(0)
|
||||
, m_resetSerial(0)
|
||||
, m_surface(nullptr)
|
||||
, m_preeditCommit()
|
||||
, m_inputPanelVisible(false)
|
||||
, m_keyboardRectangle()
|
||||
, m_locale()
|
||||
, m_inputDirection(Qt::LayoutDirectionAuto)
|
||||
, m_resetCallback(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
QString QWaylandTextInput::commitString() const
|
||||
QWaylandTextInput::~QWaylandTextInput()
|
||||
{
|
||||
return m_commit;
|
||||
if (m_resetCallback)
|
||||
wl_callback_destroy(m_resetCallback);
|
||||
}
|
||||
|
||||
void QWaylandTextInput::reset()
|
||||
{
|
||||
wl_text_input::reset();
|
||||
updateState();
|
||||
m_resetSerial = m_serial;
|
||||
m_builder.reset();
|
||||
m_preeditCommit = QString();
|
||||
updateState(Qt::ImQueryAll, update_state_reset);
|
||||
}
|
||||
|
||||
void QWaylandTextInput::updateState()
|
||||
void QWaylandTextInput::commit()
|
||||
{
|
||||
if (QObject *o = QGuiApplication::focusObject()) {
|
||||
QInputMethodEvent event;
|
||||
event.setCommitString(m_preeditCommit);
|
||||
QCoreApplication::sendEvent(o, &event);
|
||||
}
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
const wl_callback_listener QWaylandTextInput::callbackListener = {
|
||||
QWaylandTextInput::resetCallback
|
||||
};
|
||||
|
||||
void QWaylandTextInput::resetCallback(void *data, wl_callback *, uint32_t)
|
||||
{
|
||||
QWaylandTextInput *self = static_cast<QWaylandTextInput*>(data);
|
||||
|
||||
if (self->m_resetCallback) {
|
||||
wl_callback_destroy(self->m_resetCallback);
|
||||
self->m_resetCallback = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void QWaylandTextInput::updateState(Qt::InputMethodQueries queries, uint32_t flags)
|
||||
{
|
||||
if (!QGuiApplication::focusObject())
|
||||
return;
|
||||
|
||||
QInputMethodQueryEvent event(Qt::ImQueryAll);
|
||||
if (!QGuiApplication::focusWindow() || !QGuiApplication::focusWindow()->handle())
|
||||
return;
|
||||
|
||||
struct ::wl_surface *surface = static_cast<QWaylandWindow *>(QGuiApplication::focusWindow()->handle())->object();
|
||||
if (!surface || (surface != m_surface))
|
||||
return;
|
||||
|
||||
queries &= supportedQueries;
|
||||
|
||||
// Surrounding text, cursor and anchor positions are transferred together
|
||||
if ((queries & Qt::ImSurroundingText) || (queries & Qt::ImCursorPosition) || (queries & Qt::ImAnchorPosition))
|
||||
queries |= Qt::ImSurroundingText | Qt::ImCursorPosition | Qt::ImAnchorPosition;
|
||||
|
||||
QInputMethodQueryEvent event(queries);
|
||||
QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
|
||||
|
||||
const QString &text = event.value(Qt::ImSurroundingText).toString();
|
||||
const int cursor = event.value(Qt::ImCursorPosition).toInt();
|
||||
const int anchor = event.value(Qt::ImAnchorPosition).toInt();
|
||||
if ((queries & Qt::ImSurroundingText) || (queries & Qt::ImCursorPosition) || (queries & Qt::ImAnchorPosition)) {
|
||||
QString text = event.value(Qt::ImSurroundingText).toString();
|
||||
int cursor = event.value(Qt::ImCursorPosition).toInt();
|
||||
int anchor = event.value(Qt::ImAnchorPosition).toInt();
|
||||
|
||||
set_surrounding_text(text, text.leftRef(cursor).toUtf8().size(), text.leftRef(anchor).toUtf8().size());
|
||||
// Make sure text is not too big
|
||||
if (text.toUtf8().size() > 2048) {
|
||||
int c = qAbs(cursor - anchor) <= 512 ? qMin(cursor, anchor) + qAbs(cursor - anchor) / 2: cursor;
|
||||
|
||||
commit_state(++m_serial);
|
||||
const int offset = c - qBound(0, c, 512 - qMin(text.size() - c, 256));
|
||||
text = text.mid(offset + c - 256, 512);
|
||||
cursor -= offset;
|
||||
anchor -= offset;
|
||||
}
|
||||
|
||||
set_surrounding_text(text, text.leftRef(cursor).toUtf8().size(), text.leftRef(anchor).toUtf8().size());
|
||||
}
|
||||
|
||||
if (queries & Qt::ImHints) {
|
||||
QWaylandInputMethodContentType contentType = QWaylandInputMethodContentType::convert(static_cast<Qt::InputMethodHints>(event.value(Qt::ImHints).toInt()));
|
||||
set_content_type(contentType.hint, contentType.purpose);
|
||||
}
|
||||
|
||||
if (queries & Qt::ImCursorRectangle) {
|
||||
const QRect &cRect = event.value(Qt::ImCursorRectangle).toRect();
|
||||
const QRect &tRect = QGuiApplication::inputMethod()->inputItemTransform().mapRect(cRect);
|
||||
set_cursor_rectangle(tRect.x(), tRect.y(), tRect.width(), tRect.height());
|
||||
}
|
||||
|
||||
if (queries & Qt::ImPreferredLanguage) {
|
||||
const QString &language = event.value(Qt::ImPreferredLanguage).toString();
|
||||
set_preferred_language(language);
|
||||
}
|
||||
|
||||
update_state(m_serial, flags);
|
||||
if (flags != update_state_change) {
|
||||
if (m_resetCallback)
|
||||
wl_callback_destroy(m_resetCallback);
|
||||
m_resetCallback = wl_display_sync(m_display->wl_display());
|
||||
wl_callback_add_listener(m_resetCallback, &QWaylandTextInput::callbackListener, this);
|
||||
}
|
||||
}
|
||||
|
||||
void QWaylandTextInput::text_input_preedit_string(uint32_t serial, const QString &text, const QString &commit)
|
||||
bool QWaylandTextInput::isInputPanelVisible() const
|
||||
{
|
||||
Q_UNUSED(serial)
|
||||
return m_inputPanelVisible;
|
||||
}
|
||||
|
||||
QRectF QWaylandTextInput::keyboardRect() const
|
||||
{
|
||||
return m_keyboardRectangle;
|
||||
}
|
||||
|
||||
QLocale QWaylandTextInput::locale() const
|
||||
{
|
||||
return m_locale;
|
||||
}
|
||||
|
||||
Qt::LayoutDirection QWaylandTextInput::inputDirection() const
|
||||
{
|
||||
return m_inputDirection;
|
||||
}
|
||||
|
||||
void QWaylandTextInput::zwp_text_input_v2_enter(uint32_t serial, ::wl_surface *surface)
|
||||
{
|
||||
m_serial = serial;
|
||||
m_surface = surface;
|
||||
|
||||
updateState(Qt::ImQueryAll, update_state_enter);
|
||||
}
|
||||
|
||||
void QWaylandTextInput::zwp_text_input_v2_leave(uint32_t serial, ::wl_surface *surface)
|
||||
{
|
||||
m_serial = serial;
|
||||
|
||||
if (m_surface != surface) {
|
||||
qCDebug(qLcQpaInputMethods()) << Q_FUNC_INFO << "Got leave event for surface" << surface << "focused surface" << m_surface;
|
||||
}
|
||||
|
||||
m_surface = nullptr;
|
||||
}
|
||||
|
||||
void QWaylandTextInput::zwp_text_input_v2_modifiers_map(wl_array *map)
|
||||
{
|
||||
QList<QByteArray> modifiersMap = QByteArray::fromRawData(static_cast<const char*>(map->data), map->size).split('\0');
|
||||
|
||||
m_modifiersMap.clear();
|
||||
|
||||
Q_FOREACH (const QByteArray &modifier, modifiersMap) {
|
||||
if (modifier == "Shift")
|
||||
m_modifiersMap.append(Qt::ShiftModifier);
|
||||
else if (modifier == "Control")
|
||||
m_modifiersMap.append(Qt::ControlModifier);
|
||||
else if (modifier == "Alt")
|
||||
m_modifiersMap.append(Qt::AltModifier);
|
||||
else if (modifier == "Mod1")
|
||||
m_modifiersMap.append(Qt::AltModifier);
|
||||
else if (modifier == "Mod4")
|
||||
m_modifiersMap.append(Qt::MetaModifier);
|
||||
else
|
||||
m_modifiersMap.append(Qt::NoModifier);
|
||||
}
|
||||
}
|
||||
|
||||
void QWaylandTextInput::zwp_text_input_v2_input_panel_state(uint32_t visible, int32_t x, int32_t y, int32_t width, int32_t height)
|
||||
{
|
||||
const bool inputPanelVisible = (visible == input_panel_visibility_visible);
|
||||
if (m_inputPanelVisible != inputPanelVisible) {
|
||||
m_inputPanelVisible = inputPanelVisible;
|
||||
QGuiApplicationPrivate::platformIntegration()->inputContext()->emitInputPanelVisibleChanged();
|
||||
}
|
||||
const QRectF keyboardRectangle(x, y, width, height);
|
||||
if (m_keyboardRectangle != keyboardRectangle) {
|
||||
m_keyboardRectangle = keyboardRectangle;
|
||||
QGuiApplicationPrivate::platformIntegration()->inputContext()->emitKeyboardRectChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void QWaylandTextInput::zwp_text_input_v2_preedit_string(const QString &text, const QString &commit)
|
||||
{
|
||||
if (m_resetCallback) {
|
||||
qCDebug(qLcQpaInputMethods()) << "discard preedit_string: reset not confirmed";
|
||||
m_builder.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!QGuiApplication::focusObject())
|
||||
return;
|
||||
|
||||
m_commit = commit;
|
||||
QList<QInputMethodEvent::Attribute> attributes;
|
||||
QInputMethodEvent event(text, attributes);
|
||||
QInputMethodEvent event = m_builder.buildPreedit(text);
|
||||
|
||||
m_builder.reset();
|
||||
m_preeditCommit = commit;
|
||||
|
||||
QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
|
||||
}
|
||||
|
||||
void QWaylandTextInput::text_input_commit_string(uint32_t serial, const QString &text)
|
||||
void QWaylandTextInput::zwp_text_input_v2_preedit_styling(uint32_t index, uint32_t length, uint32_t style)
|
||||
{
|
||||
Q_UNUSED(serial);
|
||||
m_builder.addPreeditStyling(index, length, style);
|
||||
}
|
||||
|
||||
void QWaylandTextInput::zwp_text_input_v2_preedit_cursor(int32_t index)
|
||||
{
|
||||
m_builder.setPreeditCursor(index);
|
||||
}
|
||||
|
||||
void QWaylandTextInput::zwp_text_input_v2_commit_string(const QString &text)
|
||||
{
|
||||
if (m_resetCallback) {
|
||||
qCDebug(qLcQpaInputMethods()) << "discard commit_string: reset not confirmed";
|
||||
m_builder.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!QGuiApplication::focusObject())
|
||||
return;
|
||||
|
||||
QInputMethodEvent event;
|
||||
event.setCommitString(text);
|
||||
QInputMethodEvent event = m_builder.buildCommit(text);
|
||||
|
||||
m_builder.reset();
|
||||
|
||||
QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
|
||||
|
||||
m_commit = QString();
|
||||
}
|
||||
|
||||
void QWaylandTextInput::text_input_enter(wl_surface *)
|
||||
void QWaylandTextInput::zwp_text_input_v2_cursor_position(int32_t index, int32_t anchor)
|
||||
{
|
||||
updateState();
|
||||
m_resetSerial = m_serial;
|
||||
m_builder.setCursorPosition(index, anchor);
|
||||
}
|
||||
|
||||
void QWaylandTextInput::text_input_leave()
|
||||
void QWaylandTextInput::zwp_text_input_v2_delete_surrounding_text(uint32_t before_length, uint32_t after_length)
|
||||
{
|
||||
if (!m_commit.isEmpty())
|
||||
text_input_commit_string(0, m_commit);
|
||||
m_builder.setDeleteSurroundingText(before_length, after_length);
|
||||
}
|
||||
|
||||
void QWaylandTextInput::text_input_keysym(uint32_t serial, uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers)
|
||||
void QWaylandTextInput::zwp_text_input_v2_keysym(uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers)
|
||||
{
|
||||
Q_UNUSED(serial);
|
||||
Q_UNUSED(time);
|
||||
Q_UNUSED(modifiers);
|
||||
if (!QGuiApplication::focusObject())
|
||||
if (m_resetCallback) {
|
||||
qCDebug(qLcQpaInputMethods()) << "discard keysym: reset not confirmed";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!QGuiApplication::focusWindow())
|
||||
return;
|
||||
|
||||
// TODO: Convert modifiers to Qt::KeyboardModifiers.
|
||||
QKeyEvent event(toQEventType(state), toQtKey(sym), Qt::NoModifier);
|
||||
QCoreApplication::sendEvent(qGuiApp->focusWindow(), &event);
|
||||
Qt::KeyboardModifiers qtModifiers = modifiersToQtModifiers(modifiers);
|
||||
|
||||
QEvent::Type type = QWaylandXkb::toQtEventType(state);
|
||||
const QString &text = QWaylandXkb::textFromKeysym(sym, qtModifiers);
|
||||
int qtkey = QWaylandXkb::keysymToQtKey(sym, qtModifiers, text);
|
||||
|
||||
QWindowSystemInterface::handleKeyEvent(QGuiApplication::focusWindow(),
|
||||
time, type, qtkey, qtModifiers, text);
|
||||
}
|
||||
|
||||
void QWaylandTextInput::zwp_text_input_v2_language(const QString &language)
|
||||
{
|
||||
if (m_resetCallback) {
|
||||
qCDebug(qLcQpaInputMethods()) << "discard language: reset not confirmed";
|
||||
return;
|
||||
}
|
||||
|
||||
const QLocale locale(language);
|
||||
if (m_locale != locale) {
|
||||
m_locale = locale;
|
||||
QGuiApplicationPrivate::platformIntegration()->inputContext()->emitLocaleChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void QWaylandTextInput::zwp_text_input_v2_text_direction(uint32_t direction)
|
||||
{
|
||||
if (m_resetCallback) {
|
||||
qCDebug(qLcQpaInputMethods()) << "discard text_direction: reset not confirmed";
|
||||
return;
|
||||
}
|
||||
|
||||
const Qt::LayoutDirection inputDirection = (direction == text_direction_auto) ? Qt::LayoutDirectionAuto :
|
||||
(direction == text_direction_ltr) ? Qt::LeftToRight :
|
||||
(direction == text_direction_rtl) ? Qt::RightToLeft : Qt::LayoutDirectionAuto;
|
||||
if (m_inputDirection != inputDirection) {
|
||||
m_inputDirection = inputDirection;
|
||||
QGuiApplicationPrivate::platformIntegration()->inputContext()->emitInputDirectionChanged(m_inputDirection);
|
||||
}
|
||||
}
|
||||
|
||||
void QWaylandTextInput::zwp_text_input_v2_input_method_changed(uint32_t serial, uint32_t flags)
|
||||
{
|
||||
Q_UNUSED(flags);
|
||||
|
||||
m_serial = serial;
|
||||
updateState(Qt::ImQueryAll, update_state_full);
|
||||
}
|
||||
|
||||
Qt::KeyboardModifiers QWaylandTextInput::modifiersToQtModifiers(uint32_t modifiers)
|
||||
{
|
||||
Qt::KeyboardModifiers ret = Qt::NoModifier;
|
||||
for (int i = 0; modifiers >>= 1; ++i) {
|
||||
ret |= m_modifiersMap[i];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QWaylandInputContext::QWaylandInputContext(QWaylandDisplay *display)
|
||||
: QPlatformInputContext()
|
||||
, mDisplay(display)
|
||||
, mTextInput()
|
||||
, mCurrentWindow()
|
||||
{
|
||||
}
|
||||
|
||||
QWaylandInputContext::~QWaylandInputContext()
|
||||
{
|
||||
}
|
||||
|
||||
@ -191,96 +402,141 @@ bool QWaylandInputContext::isValid() const
|
||||
|
||||
void QWaylandInputContext::reset()
|
||||
{
|
||||
if (!ensureTextInput())
|
||||
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
|
||||
|
||||
QPlatformInputContext::reset();
|
||||
|
||||
if (!textInput())
|
||||
return;
|
||||
|
||||
mTextInput->reset();
|
||||
textInput()->reset();
|
||||
}
|
||||
|
||||
void QWaylandInputContext::commit()
|
||||
{
|
||||
if (!ensureTextInput())
|
||||
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
|
||||
|
||||
if (!textInput())
|
||||
return;
|
||||
|
||||
if (!QGuiApplication::focusObject())
|
||||
return;
|
||||
|
||||
QInputMethodEvent event;
|
||||
event.setCommitString(mTextInput->commitString());
|
||||
QCoreApplication::sendEvent(QGuiApplication::focusObject(), &event);
|
||||
|
||||
mTextInput->reset();
|
||||
textInput()->commit();
|
||||
}
|
||||
|
||||
void QWaylandInputContext::update(Qt::InputMethodQueries queries)
|
||||
{
|
||||
Q_UNUSED(queries);
|
||||
if (!ensureTextInput())
|
||||
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO << queries;
|
||||
|
||||
if (!QGuiApplication::focusObject() || !textInput())
|
||||
return;
|
||||
|
||||
mTextInput->updateState();
|
||||
}
|
||||
if (mCurrentWindow && mCurrentWindow->handle() && !inputMethodAccepted()) {
|
||||
struct ::wl_surface *surface = static_cast<QWaylandWindow *>(mCurrentWindow->handle())->object();
|
||||
textInput()->disable(surface);
|
||||
mCurrentWindow.clear();
|
||||
} else if (!mCurrentWindow && inputMethodAccepted()) {
|
||||
QWindow *window = QGuiApplication::focusWindow();
|
||||
if (window && window->handle()) {
|
||||
struct ::wl_surface *surface = static_cast<QWaylandWindow *>(window->handle())->object();
|
||||
textInput()->enable(surface);
|
||||
mCurrentWindow = window;
|
||||
}
|
||||
}
|
||||
|
||||
void QWaylandInputContext::invokeAction(QInputMethod::Action, int cursorPosition)
|
||||
{
|
||||
if (!ensureTextInput())
|
||||
return;
|
||||
|
||||
mTextInput->invoke_action(0, cursorPosition); // FIXME button, to UTF8 cursor position
|
||||
textInput()->updateState(queries, QtWayland::zwp_text_input_v2::update_state_change);
|
||||
}
|
||||
|
||||
void QWaylandInputContext::showInputPanel()
|
||||
{
|
||||
if (!ensureTextInput())
|
||||
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
|
||||
|
||||
if (!textInput())
|
||||
return;
|
||||
|
||||
mTextInput->show_input_panel();
|
||||
textInput()->show_input_panel();
|
||||
}
|
||||
|
||||
void QWaylandInputContext::hideInputPanel()
|
||||
{
|
||||
if (!ensureTextInput())
|
||||
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
|
||||
|
||||
if (!textInput())
|
||||
return;
|
||||
|
||||
mTextInput->hide_input_panel();
|
||||
textInput()->hide_input_panel();
|
||||
}
|
||||
|
||||
bool QWaylandInputContext::isInputPanelVisible() const
|
||||
{
|
||||
return false;
|
||||
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
|
||||
|
||||
if (!textInput())
|
||||
return QPlatformInputContext::isInputPanelVisible();
|
||||
|
||||
return textInput()->isInputPanelVisible();
|
||||
}
|
||||
|
||||
void QWaylandInputContext::setFocusObject(QObject *object)
|
||||
QRectF QWaylandInputContext::keyboardRect() const
|
||||
{
|
||||
if (!ensureTextInput())
|
||||
return;
|
||||
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
|
||||
|
||||
if (!object) {
|
||||
mTextInput->deactivate(mDisplay->defaultInputDevice()->wl_seat());
|
||||
if (!textInput())
|
||||
return QPlatformInputContext::keyboardRect();
|
||||
|
||||
return textInput()->keyboardRect();
|
||||
}
|
||||
|
||||
QLocale QWaylandInputContext::locale() const
|
||||
{
|
||||
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
|
||||
|
||||
if (!textInput())
|
||||
return QPlatformInputContext::locale();
|
||||
|
||||
return textInput()->locale();
|
||||
}
|
||||
|
||||
Qt::LayoutDirection QWaylandInputContext::inputDirection() const
|
||||
{
|
||||
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
|
||||
|
||||
if (!textInput())
|
||||
return QPlatformInputContext::inputDirection();
|
||||
|
||||
return textInput()->inputDirection();
|
||||
}
|
||||
|
||||
void QWaylandInputContext::setFocusObject(QObject *)
|
||||
{
|
||||
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
|
||||
|
||||
if (!textInput())
|
||||
return;
|
||||
}
|
||||
|
||||
QWindow *window = QGuiApplication::focusWindow();
|
||||
if (!window || !window->handle())
|
||||
return;
|
||||
|
||||
struct ::wl_surface *surface = static_cast<QWaylandWindow *>(window->handle())->object();
|
||||
mTextInput->activate(mDisplay->defaultInputDevice()->wl_seat(), surface);
|
||||
if (mCurrentWindow && mCurrentWindow->handle()) {
|
||||
if (mCurrentWindow.data() != window || !inputMethodAccepted()) {
|
||||
struct ::wl_surface *surface = static_cast<QWaylandWindow *>(mCurrentWindow->handle())->object();
|
||||
textInput()->disable(surface);
|
||||
mCurrentWindow.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (window && window->handle() && inputMethodAccepted()) {
|
||||
if (mCurrentWindow.data() != window) {
|
||||
struct ::wl_surface *surface = static_cast<QWaylandWindow *>(window->handle())->object();
|
||||
textInput()->enable(surface);
|
||||
mCurrentWindow = window;
|
||||
}
|
||||
textInput()->updateState(Qt::ImQueryAll, QtWayland::zwp_text_input_v2::update_state_enter);
|
||||
}
|
||||
}
|
||||
|
||||
bool QWaylandInputContext::ensureTextInput()
|
||||
QWaylandTextInput *QWaylandInputContext::textInput() const
|
||||
{
|
||||
if (mTextInput)
|
||||
return true;
|
||||
|
||||
if (!isValid())
|
||||
return false;
|
||||
|
||||
mTextInput.reset(new QWaylandTextInput(mDisplay->textInputManager()->create_text_input()));
|
||||
return true;
|
||||
return mDisplay->defaultInputDevice()->textInput();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Klarälvdalens Datakonsult AB (KDAB).
|
||||
** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtWaylandClient module of the Qt Toolkit.
|
||||
@ -54,36 +54,75 @@
|
||||
|
||||
#include <qpa/qplatforminputcontext.h>
|
||||
|
||||
#include <QtWaylandClient/private/qwayland-text.h>
|
||||
#include <QLoggingCategory>
|
||||
#include <QPointer>
|
||||
#include <QRectF>
|
||||
#include <QVector>
|
||||
|
||||
#include <QtWaylandClient/private/qwayland-text-input-unstable-v2.h>
|
||||
#include <qwaylandinputmethodeventbuilder.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(qLcQpaInputMethods)
|
||||
|
||||
namespace QtWaylandClient {
|
||||
|
||||
class QWaylandDisplay;
|
||||
|
||||
class QWaylandTextInput : public QtWayland::wl_text_input
|
||||
class QWaylandTextInput : public QtWayland::zwp_text_input_v2
|
||||
{
|
||||
public:
|
||||
QWaylandTextInput(struct ::wl_text_input *text_input);
|
||||
|
||||
QString commitString() const;
|
||||
QWaylandTextInput(QWaylandDisplay *display, struct ::zwp_text_input_v2 *text_input);
|
||||
~QWaylandTextInput();
|
||||
|
||||
void reset();
|
||||
void updateState();
|
||||
void commit();
|
||||
void updateState(Qt::InputMethodQueries queries, uint32_t flags);
|
||||
|
||||
bool isInputPanelVisible() const;
|
||||
QRectF keyboardRect() const;
|
||||
|
||||
QLocale locale() const;
|
||||
Qt::LayoutDirection inputDirection() const;
|
||||
|
||||
protected:
|
||||
void text_input_preedit_string(uint32_t serial, const QString &text, const QString &commit) Q_DECL_OVERRIDE;
|
||||
void text_input_commit_string(uint32_t serial, const QString &text) Q_DECL_OVERRIDE;
|
||||
void text_input_enter(wl_surface *surface) Q_DECL_OVERRIDE;
|
||||
void text_input_leave() Q_DECL_OVERRIDE;
|
||||
void text_input_keysym(uint32_t serial, uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers);
|
||||
void zwp_text_input_v2_enter(uint32_t serial, struct ::wl_surface *surface) Q_DECL_OVERRIDE;
|
||||
void zwp_text_input_v2_leave(uint32_t serial, struct ::wl_surface *surface) Q_DECL_OVERRIDE;
|
||||
void zwp_text_input_v2_modifiers_map(wl_array *map) Q_DECL_OVERRIDE;
|
||||
void zwp_text_input_v2_input_panel_state(uint32_t state, int32_t x, int32_t y, int32_t width, int32_t height) Q_DECL_OVERRIDE;
|
||||
void zwp_text_input_v2_preedit_string(const QString &text, const QString &commit) Q_DECL_OVERRIDE;
|
||||
void zwp_text_input_v2_preedit_styling(uint32_t index, uint32_t length, uint32_t style) Q_DECL_OVERRIDE;
|
||||
void zwp_text_input_v2_preedit_cursor(int32_t index) Q_DECL_OVERRIDE;
|
||||
void zwp_text_input_v2_commit_string(const QString &text) Q_DECL_OVERRIDE;
|
||||
void zwp_text_input_v2_cursor_position(int32_t index, int32_t anchor) Q_DECL_OVERRIDE;
|
||||
void zwp_text_input_v2_delete_surrounding_text(uint32_t before_length, uint32_t after_length) Q_DECL_OVERRIDE;
|
||||
void zwp_text_input_v2_keysym(uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers) Q_DECL_OVERRIDE;
|
||||
void zwp_text_input_v2_language(const QString &language) Q_DECL_OVERRIDE;
|
||||
void zwp_text_input_v2_text_direction(uint32_t direction) Q_DECL_OVERRIDE;
|
||||
void zwp_text_input_v2_input_method_changed(uint32_t serial, uint32_t flags) Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
QString m_commit;
|
||||
Qt::KeyboardModifiers modifiersToQtModifiers(uint32_t modifiers);
|
||||
|
||||
QWaylandDisplay *m_display;
|
||||
QWaylandInputMethodEventBuilder m_builder;
|
||||
|
||||
QVector<Qt::KeyboardModifier> m_modifiersMap;
|
||||
|
||||
uint32_t m_serial;
|
||||
uint32_t m_resetSerial;
|
||||
struct ::wl_surface *m_surface;
|
||||
|
||||
QString m_preeditCommit;
|
||||
|
||||
bool m_inputPanelVisible;
|
||||
QRectF m_keyboardRectangle;
|
||||
QLocale m_locale;
|
||||
Qt::LayoutDirection m_inputDirection;
|
||||
|
||||
struct ::wl_callback *m_resetCallback;
|
||||
static const wl_callback_listener callbackListener;
|
||||
static void resetCallback(void *data, struct wl_callback *wl_callback, uint32_t time);
|
||||
};
|
||||
|
||||
class QWaylandInputContext : public QPlatformInputContext
|
||||
@ -91,25 +130,29 @@ class QWaylandInputContext : public QPlatformInputContext
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QWaylandInputContext(QWaylandDisplay *display);
|
||||
~QWaylandInputContext();
|
||||
|
||||
bool isValid() const Q_DECL_OVERRIDE;
|
||||
|
||||
void reset() Q_DECL_OVERRIDE;
|
||||
void commit() Q_DECL_OVERRIDE;
|
||||
void update(Qt::InputMethodQueries) Q_DECL_OVERRIDE;
|
||||
void invokeAction(QInputMethod::Action, int cursorPosition) Q_DECL_OVERRIDE;
|
||||
|
||||
void showInputPanel() Q_DECL_OVERRIDE;
|
||||
void hideInputPanel() Q_DECL_OVERRIDE;
|
||||
bool isInputPanelVisible() const Q_DECL_OVERRIDE;
|
||||
QRectF keyboardRect() const Q_DECL_OVERRIDE;
|
||||
|
||||
QLocale locale() const Q_DECL_OVERRIDE;
|
||||
Qt::LayoutDirection inputDirection() const Q_DECL_OVERRIDE;
|
||||
|
||||
void setFocusObject(QObject *object) Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
bool ensureTextInput();
|
||||
QWaylandTextInput *textInput() const;
|
||||
|
||||
QWaylandDisplay *mDisplay;
|
||||
QScopedPointer<QWaylandTextInput> mTextInput;
|
||||
QPointer<QWindow> mCurrentWindow;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "qwaylanddisplay_p.h"
|
||||
#include "qwaylandshmbackingstore_p.h"
|
||||
#include "../shared/qwaylandxkb.h"
|
||||
#include "qwaylandinputcontext_p.h"
|
||||
|
||||
#include <QtGui/private/qpixmap_raster_p.h>
|
||||
#include <QtGui/private/qguiapplication_p.h>
|
||||
@ -185,6 +186,7 @@ QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, int version,
|
||||
, mKeyboard(0)
|
||||
, mPointer(0)
|
||||
, mTouch(0)
|
||||
, mTextInput(0)
|
||||
, mTime(0)
|
||||
, mSerial(0)
|
||||
, mTouchDevice(0)
|
||||
@ -193,6 +195,9 @@ QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, int version,
|
||||
mDataDevice = mQDisplay->dndSelectionHandler()->getDataDevice(this);
|
||||
}
|
||||
|
||||
if (mQDisplay->textInputManager()) {
|
||||
mTextInput = new QWaylandTextInput(mQDisplay, mQDisplay->textInputManager()->get_text_input(wl_seat()));
|
||||
}
|
||||
}
|
||||
|
||||
QWaylandInputDevice::~QWaylandInputDevice()
|
||||
@ -277,6 +282,16 @@ QWaylandDataDevice *QWaylandInputDevice::dataDevice() const
|
||||
return mDataDevice;
|
||||
}
|
||||
|
||||
void QWaylandInputDevice::setTextInput(QWaylandTextInput *textInput)
|
||||
{
|
||||
mTextInput = textInput;
|
||||
}
|
||||
|
||||
QWaylandTextInput *QWaylandInputDevice::textInput() const
|
||||
{
|
||||
return mTextInput;
|
||||
}
|
||||
|
||||
void QWaylandInputDevice::removeMouseButtonFromState(Qt::MouseButton button)
|
||||
{
|
||||
if (mPointer)
|
||||
@ -693,19 +708,9 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time,
|
||||
|
||||
Qt::KeyboardModifiers modifiers = mParent->modifiers();
|
||||
|
||||
uint utf32 = xkb_keysym_to_utf32(sym);
|
||||
if (utf32)
|
||||
text = QString::fromUcs4(&utf32, 1);
|
||||
|
||||
text = QWaylandXkb::textFromKeysym(sym, modifiers);
|
||||
qtkey = QWaylandXkb::keysymToQtKey(sym, modifiers, text);
|
||||
|
||||
|
||||
// Map control + letter to proper text
|
||||
if (utf32 >= 'A' && utf32 <= '~' && (modifiers & Qt::ControlModifier)) {
|
||||
utf32 &= ~0x60;
|
||||
text = QString::fromUcs4(&utf32, 1);
|
||||
}
|
||||
|
||||
sendKey(window->window(), time, type, qtkey, modifiers, code, sym, mNativeModifiers, text);
|
||||
#else
|
||||
// Generic fallback for single hard keys: Assume 'key' is a Qt key code.
|
||||
|
@ -80,6 +80,7 @@ namespace QtWaylandClient {
|
||||
class QWaylandWindow;
|
||||
class QWaylandDisplay;
|
||||
class QWaylandDataDevice;
|
||||
class QWaylandTextInput;
|
||||
|
||||
class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDevice
|
||||
: public QObject
|
||||
@ -108,6 +109,9 @@ public:
|
||||
void setDataDevice(QWaylandDataDevice *device);
|
||||
QWaylandDataDevice *dataDevice() const;
|
||||
|
||||
void setTextInput(QWaylandTextInput *textInput);
|
||||
QWaylandTextInput *textInput() const;
|
||||
|
||||
void removeMouseButtonFromState(Qt::MouseButton button);
|
||||
|
||||
QWaylandWindow *pointerFocus() const;
|
||||
@ -138,6 +142,8 @@ private:
|
||||
Pointer *mPointer;
|
||||
Touch *mTouch;
|
||||
|
||||
QWaylandTextInput *mTextInput;
|
||||
|
||||
uint32_t mTime;
|
||||
uint32_t mSerial;
|
||||
|
||||
|
@ -0,0 +1,286 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qwaylandinputmethodeventbuilder.h"
|
||||
|
||||
#include <QInputMethod>
|
||||
#include <QTextCharFormat>
|
||||
|
||||
#ifdef QT_BUILD_WAYLANDCOMPOSITOR_LIB
|
||||
#include <QtWaylandCompositor/private/qwayland-server-text-input-unstable-v2.h>
|
||||
#else
|
||||
#include <QtWaylandClient/private/qwayland-text-input-unstable-v2.h>
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QWaylandInputMethodEventBuilder::QWaylandInputMethodEventBuilder()
|
||||
: m_anchor(0)
|
||||
, m_cursor(0)
|
||||
, m_deleteBefore(0)
|
||||
, m_deleteAfter(0)
|
||||
, m_preeditCursor(0)
|
||||
, m_preeditStyles()
|
||||
{
|
||||
}
|
||||
|
||||
QWaylandInputMethodEventBuilder::~QWaylandInputMethodEventBuilder()
|
||||
{
|
||||
}
|
||||
|
||||
void QWaylandInputMethodEventBuilder::reset()
|
||||
{
|
||||
m_anchor = 0;
|
||||
m_cursor = 0;
|
||||
m_deleteBefore = 0;
|
||||
m_deleteAfter = 0;
|
||||
m_preeditCursor = 0;
|
||||
m_preeditStyles.clear();
|
||||
}
|
||||
|
||||
void QWaylandInputMethodEventBuilder::setCursorPosition(int32_t index, int32_t anchor)
|
||||
{
|
||||
m_cursor = index;
|
||||
m_anchor = anchor;
|
||||
}
|
||||
|
||||
void QWaylandInputMethodEventBuilder::setDeleteSurroundingText(uint32_t beforeLength, uint32_t afterLength)
|
||||
{
|
||||
m_deleteBefore = beforeLength;
|
||||
m_deleteAfter = afterLength;
|
||||
}
|
||||
|
||||
void QWaylandInputMethodEventBuilder::addPreeditStyling(uint32_t index, uint32_t length, uint32_t style)
|
||||
{
|
||||
QTextCharFormat format;
|
||||
|
||||
switch (style) {
|
||||
case 0:
|
||||
case 1:
|
||||
format.setFontUnderline(true);
|
||||
format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
|
||||
m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
format.setFontWeight(QFont::Bold);
|
||||
format.setFontUnderline(true);
|
||||
format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
|
||||
m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
|
||||
break;
|
||||
case 4:
|
||||
format.setFontUnderline(true);
|
||||
format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
|
||||
m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
|
||||
case 5:
|
||||
format.setFontUnderline(true);
|
||||
format.setUnderlineStyle(QTextCharFormat::WaveUnderline);
|
||||
format.setUnderlineColor(QColor(Qt::red));
|
||||
m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
|
||||
break;
|
||||
// case QtWayland::wl_text_input::preedit_style_selection:
|
||||
// case QtWayland::wl_text_input::preedit_style_none:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QWaylandInputMethodEventBuilder::setPreeditCursor(int32_t index)
|
||||
{
|
||||
m_preeditCursor = index;
|
||||
}
|
||||
|
||||
QInputMethodEvent QWaylandInputMethodEventBuilder::buildCommit(const QString &text)
|
||||
{
|
||||
QList<QInputMethodEvent::Attribute> attributes;
|
||||
|
||||
const QPair<int, int> replacement = replacementForDeleteSurrounding();
|
||||
|
||||
if (m_cursor != 0 || m_anchor != 0) {
|
||||
QString surrounding = QInputMethod::queryFocusObject(Qt::ImSurroundingText, QVariant()).toString();
|
||||
const int cursor = QInputMethod::queryFocusObject(Qt::ImCursorPosition, QVariant()).toInt();
|
||||
const int anchor = QInputMethod::queryFocusObject(Qt::ImAnchorPosition, QVariant()).toInt();
|
||||
const int absoluteCursor = QInputMethod::queryFocusObject(Qt::ImAbsolutePosition, QVariant()).toInt();
|
||||
|
||||
const int absoluteOffset = absoluteCursor - cursor;
|
||||
|
||||
const int cursorAfterCommit = qMin(anchor, cursor) + replacement.first + text.length();
|
||||
surrounding.replace(qMin(anchor, cursor) + replacement.first,
|
||||
qAbs(anchor - cursor) + replacement.second, text);
|
||||
|
||||
attributes.push_back(QInputMethodEvent::Attribute(QInputMethodEvent::Selection,
|
||||
indexFromWayland(surrounding, m_cursor, cursorAfterCommit) + absoluteOffset,
|
||||
indexFromWayland(surrounding, m_anchor, cursorAfterCommit) + absoluteOffset,
|
||||
QVariant()));
|
||||
}
|
||||
|
||||
QInputMethodEvent event(QString(), attributes);
|
||||
event.setCommitString(text, replacement.first, replacement.second);
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
QInputMethodEvent QWaylandInputMethodEventBuilder::buildPreedit(const QString &text)
|
||||
{
|
||||
QList<QInputMethodEvent::Attribute> attributes;
|
||||
|
||||
if (m_preeditCursor < 0) {
|
||||
attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 0, QVariant()));
|
||||
} else if (m_preeditCursor > 0) {
|
||||
attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, indexFromWayland(text, m_preeditCursor), 1, QVariant()));
|
||||
}
|
||||
|
||||
Q_FOREACH (const QInputMethodEvent::Attribute &attr, m_preeditStyles) {
|
||||
int start = indexFromWayland(text, attr.start);
|
||||
int length = indexFromWayland(text, attr.start + attr.length) - start;
|
||||
attributes.append(QInputMethodEvent::Attribute(attr.type, start, length, attr.value));
|
||||
}
|
||||
|
||||
QInputMethodEvent event(text, attributes);
|
||||
|
||||
const QPair<int, int> replacement = replacementForDeleteSurrounding();
|
||||
event.setCommitString(QString(), replacement.first, replacement.second);
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
QPair<int, int> QWaylandInputMethodEventBuilder::replacementForDeleteSurrounding()
|
||||
{
|
||||
if (m_deleteBefore == 0 && m_deleteAfter == 0)
|
||||
return QPair<int, int>(0, 0);
|
||||
|
||||
const QString &surrounding = QInputMethod::queryFocusObject(Qt::ImSurroundingText, QVariant()).toString();
|
||||
const int cursor = QInputMethod::queryFocusObject(Qt::ImCursorPosition, QVariant()).toInt();
|
||||
const int anchor = QInputMethod::queryFocusObject(Qt::ImAnchorPosition, QVariant()).toInt();
|
||||
|
||||
const int selectionStart = qMin(cursor, anchor);
|
||||
const int selectionEnd = qMax(cursor, anchor);
|
||||
|
||||
const int deleteBefore = selectionStart - indexFromWayland(surrounding, -m_deleteBefore, selectionStart);
|
||||
const int deleteAfter = indexFromWayland(surrounding, m_deleteAfter, selectionEnd) - selectionEnd;
|
||||
|
||||
return QPair<int, int>(-deleteBefore, deleteBefore + deleteAfter);
|
||||
}
|
||||
|
||||
QWaylandInputMethodContentType QWaylandInputMethodContentType::convert(Qt::InputMethodHints hints)
|
||||
{
|
||||
uint32_t hint = ZWP_TEXT_INPUT_V2_CONTENT_HINT_NONE;
|
||||
uint32_t purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_NORMAL;
|
||||
|
||||
if (hints & Qt::ImhHiddenText) {
|
||||
hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_HIDDEN_TEXT;
|
||||
}
|
||||
if (hints & Qt::ImhSensitiveData) {
|
||||
hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_SENSITIVE_DATA;
|
||||
}
|
||||
if ((hints & Qt::ImhNoAutoUppercase) == 0) {
|
||||
hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_AUTO_CAPITALIZATION;
|
||||
}
|
||||
if (hints & Qt::ImhPreferNumbers) {
|
||||
// Nothing yet
|
||||
}
|
||||
if (hints & Qt::ImhPreferUppercase) {
|
||||
hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_UPPERCASE;
|
||||
}
|
||||
if (hints & Qt::ImhPreferLowercase) {
|
||||
hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_LOWERCASE;
|
||||
}
|
||||
if ((hints & Qt::ImhNoPredictiveText) == 0) {
|
||||
hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_AUTO_COMPLETION | ZWP_TEXT_INPUT_V2_CONTENT_HINT_AUTO_CORRECTION;
|
||||
}
|
||||
|
||||
if ((hints & Qt::ImhDate) && (hints & Qt::ImhTime) == 0) {
|
||||
purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_DATE;
|
||||
} else if ((hints & Qt::ImhDate) && (hints & Qt::ImhTime)) {
|
||||
purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_DATETIME;
|
||||
} else if ((hints & Qt::ImhDate) == 0 && (hints & Qt::ImhTime)) {
|
||||
purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_TIME;
|
||||
}
|
||||
|
||||
if (hints & Qt::ImhPreferLatin) {
|
||||
hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_LATIN;
|
||||
}
|
||||
|
||||
if (hints & Qt::ImhMultiLine) {
|
||||
hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_MULTILINE;
|
||||
}
|
||||
|
||||
if (hints & Qt::ImhDigitsOnly) {
|
||||
purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_DIGITS;
|
||||
}
|
||||
if (hints & Qt::ImhFormattedNumbersOnly) {
|
||||
purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_NUMBER;
|
||||
}
|
||||
if (hints & Qt::ImhUppercaseOnly) {
|
||||
hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_UPPERCASE;
|
||||
}
|
||||
if (hints & Qt::ImhLowercaseOnly) {
|
||||
hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_LOWERCASE;
|
||||
}
|
||||
if (hints & Qt::ImhDialableCharactersOnly) {
|
||||
purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_PHONE;
|
||||
}
|
||||
if (hints & Qt::ImhEmailCharactersOnly) {
|
||||
purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_EMAIL;
|
||||
}
|
||||
if (hints & Qt::ImhUrlCharactersOnly) {
|
||||
purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_URL;
|
||||
}
|
||||
if (hints & Qt::ImhLatinOnly) {
|
||||
hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_LATIN;
|
||||
}
|
||||
return QWaylandInputMethodContentType{hint, purpose};
|
||||
}
|
||||
|
||||
int QWaylandInputMethodEventBuilder::indexFromWayland(const QString &str, int utf8Index, int baseIndex)
|
||||
{
|
||||
if (utf8Index == 0)
|
||||
return baseIndex;
|
||||
|
||||
if (utf8Index < 0) {
|
||||
const QByteArray &utf8 = str.leftRef(baseIndex).toUtf8();
|
||||
return QString::fromUtf8(utf8.left(qMax(utf8.length() + utf8Index, 0))).length();
|
||||
} else {
|
||||
const QByteArray &utf8 = str.midRef(baseIndex).toUtf8();
|
||||
return QString::fromUtf8(utf8.left(utf8Index)).length() + baseIndex;
|
||||
}
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -0,0 +1,87 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QWAYLANDINPUTMETHODEVENTBUILDER_H
|
||||
#define QWAYLANDINPUTMETHODEVENTBUILDER_H
|
||||
|
||||
#include <QInputMethodEvent>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QWaylandInputMethodEventBuilder
|
||||
{
|
||||
public:
|
||||
QWaylandInputMethodEventBuilder();
|
||||
~QWaylandInputMethodEventBuilder();
|
||||
|
||||
void reset();
|
||||
|
||||
void setCursorPosition(int32_t index, int32_t anchor);
|
||||
void setDeleteSurroundingText(uint32_t beforeLength, uint32_t afterLength);
|
||||
|
||||
void addPreeditStyling(uint32_t index, uint32_t length, uint32_t style);
|
||||
void setPreeditCursor(int32_t index);
|
||||
|
||||
QInputMethodEvent buildCommit(const QString &text);
|
||||
QInputMethodEvent buildPreedit(const QString &text);
|
||||
|
||||
static int indexFromWayland(const QString &str, int utf8Index, int baseIndex = 0);
|
||||
private:
|
||||
QPair<int, int> replacementForDeleteSurrounding();
|
||||
|
||||
int32_t m_anchor;
|
||||
int32_t m_cursor;
|
||||
uint32_t m_deleteBefore;
|
||||
uint32_t m_deleteAfter;
|
||||
|
||||
int32_t m_preeditCursor;
|
||||
QList<QInputMethodEvent::Attribute> m_preeditStyles;
|
||||
};
|
||||
|
||||
struct QWaylandInputMethodContentType {
|
||||
uint32_t hint;
|
||||
uint32_t purpose;
|
||||
|
||||
static QWaylandInputMethodContentType convert(Qt::InputMethodHints hints);
|
||||
};
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QWAYLANDINPUTMETHODEVENTBUILDER_H
|
@ -40,6 +40,7 @@
|
||||
|
||||
#include "qwaylandxkb.h"
|
||||
|
||||
#include <QKeyEvent>
|
||||
#include <QString>
|
||||
|
||||
#ifndef QT_NO_WAYLAND_XKB
|
||||
@ -282,6 +283,16 @@ static int lookupKeysym(xkb_keysym_t key)
|
||||
return code;
|
||||
}
|
||||
|
||||
static xkb_keysym_t toKeysymFromTable(uint32_t key)
|
||||
{
|
||||
for (int i = 0; KeyTbl[i]; i += 2) {
|
||||
if (key == KeyTbl[i + 1])
|
||||
return KeyTbl[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int QWaylandXkb::keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, const QString &text)
|
||||
{
|
||||
int code = 0;
|
||||
@ -326,6 +337,50 @@ Qt::KeyboardModifiers QWaylandXkb::modifiers(struct xkb_state *state)
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
QEvent::Type QWaylandXkb::toQtEventType(uint32_t state)
|
||||
{
|
||||
return state != 0 ? QEvent::KeyPress : QEvent::KeyRelease;
|
||||
}
|
||||
|
||||
QString QWaylandXkb::textFromKeysym(uint32_t keysym, Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
uint utf32 = xkb_keysym_to_utf32(keysym);
|
||||
|
||||
// Map control + letter to proper text
|
||||
if (utf32 >= 'A' && utf32 <= '~' && (modifiers & Qt::ControlModifier)) {
|
||||
utf32 &= ~0x60;
|
||||
return QString::fromUcs4(&utf32, 1);
|
||||
}
|
||||
|
||||
if (utf32)
|
||||
return QString::fromUcs4(&utf32, 1);
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QVector<xkb_keysym_t> QWaylandXkb::toKeysym(QKeyEvent *event)
|
||||
{
|
||||
QVector<xkb_keysym_t> keysyms;
|
||||
if (event->key() >= Qt::Key_F1 && event->key() <= Qt::Key_F35) {
|
||||
keysyms.append(XKB_KEY_F1 + (event->key() - Qt::Key_F1));
|
||||
} else if (event->modifiers() & Qt::KeypadModifier) {
|
||||
if (event->key() >= Qt::Key_0 && event->key() <= Qt::Key_9)
|
||||
keysyms.append(XKB_KEY_KP_0 + (event->key() - Qt::Key_0));
|
||||
else
|
||||
keysyms.append(toKeysymFromTable(event->key()));
|
||||
} else if (!event->text().isEmpty()) {
|
||||
// From libxkbcommon keysym-utf.c:
|
||||
// "We allow to represent any UCS character in the range U-00000000 to
|
||||
// U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff."
|
||||
foreach (uint utf32, event->text().toUcs4()) {
|
||||
keysyms.append(utf32 | 0x01000000);
|
||||
}
|
||||
} else {
|
||||
keysyms.append(toKeysymFromTable(event->key()));
|
||||
}
|
||||
return keysyms;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QT_NO_WAYLAND_XKB
|
||||
|
@ -44,15 +44,22 @@
|
||||
#ifndef QT_NO_WAYLAND_XKB
|
||||
|
||||
#include <Qt>
|
||||
#include <QEvent>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QKeyEvent;
|
||||
|
||||
class QWaylandXkb
|
||||
{
|
||||
public:
|
||||
static int keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, const QString &text);
|
||||
static Qt::KeyboardModifiers modifiers(struct xkb_state *state);
|
||||
|
||||
static QEvent::Type toQtEventType(uint32_t state);
|
||||
static QString textFromKeysym(uint32_t keysym, Qt::KeyboardModifiers modifiers);
|
||||
static QVector<xkb_keysym_t> toKeysym(QKeyEvent *event);
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
Loading…
x
Reference in New Issue
Block a user