summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/protocol/input-method.xml273
-rw-r--r--src/3rdparty/protocol/text-input-unstable-v2.xml478
-rw-r--r--src/3rdparty/protocol/text.xml346
-rw-r--r--src/client/client.pro4
-rw-r--r--src/client/qwaylanddisplay.cpp10
-rw-r--r--src/client/qwaylanddisplay_p.h6
-rw-r--r--src/client/qwaylandinputcontext.cpp506
-rw-r--r--src/client/qwaylandinputcontext_p.h77
-rw-r--r--src/client/qwaylandinputdevice.cpp27
-rw-r--r--src/client/qwaylandinputdevice_p.h6
-rw-r--r--src/compositor/compositor.pro4
-rw-r--r--src/compositor/compositor_api/compositor_api.pri5
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor.cpp2
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor.h3
-rw-r--r--src/compositor/compositor_api/qwaylandinput.cpp13
-rw-r--r--src/compositor/compositor_api/qwaylandinputmethodcontrol.cpp162
-rw-r--r--src/compositor/compositor_api/qwaylandinputmethodcontrol.h (renamed from src/compositor/compositor_api/qwaylandinputpanel.cpp)67
-rw-r--r--src/compositor/compositor_api/qwaylandinputmethodcontrol_p.h (renamed from src/compositor/compositor_api/qwaylandinputpanel.h)52
-rw-r--r--src/compositor/compositor_api/qwaylandquickitem.cpp60
-rw-r--r--src/compositor/compositor_api/qwaylandquickitem.h12
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.cpp20
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.h5
-rw-r--r--src/compositor/compositor_api/qwaylandsurface_p.h7
-rw-r--r--src/compositor/extensions/extensions.pri21
-rw-r--r--src/compositor/extensions/qwaylandtextinput.cpp591
-rw-r--r--src/compositor/extensions/qwaylandtextinput.h (renamed from src/compositor/extensions/qwlinputpanelsurface_p.h)73
-rw-r--r--src/compositor/extensions/qwaylandtextinput_p.h135
-rw-r--r--src/compositor/extensions/qwaylandtextinputmanager.cpp98
-rw-r--r--src/compositor/extensions/qwaylandtextinputmanager.h (renamed from src/compositor/extensions/qwltextinputmanager.cpp)38
-rw-r--r--src/compositor/extensions/qwaylandtextinputmanager_p.h (renamed from src/compositor/extensions/qwltextinputmanager_p.h)31
-rw-r--r--src/compositor/extensions/qwlinputmethod.cpp152
-rw-r--r--src/compositor/extensions/qwlinputmethod_p.h105
-rw-r--r--src/compositor/extensions/qwlinputmethodcontext.cpp135
-rw-r--r--src/compositor/extensions/qwlinputmethodcontext_p.h90
-rw-r--r--src/compositor/extensions/qwlinputpanel.cpp130
-rw-r--r--src/compositor/extensions/qwlinputpanel_p.h99
-rw-r--r--src/compositor/extensions/qwlinputpanelsurface.cpp86
-rw-r--r--src/compositor/extensions/qwltextinput.cpp212
-rw-r--r--src/compositor/extensions/qwltextinput_p.h106
-rw-r--r--src/imports/compositor/qwaylandquickcompositorplugin.cpp5
-rw-r--r--src/shared/qwaylandinputmethodeventbuilder.cpp286
-rw-r--r--src/shared/qwaylandinputmethodeventbuilder.h87
-rw-r--r--src/shared/qwaylandxkb.cpp55
-rw-r--r--src/shared/qwaylandxkb.h7
44 files changed, 2616 insertions, 2071 deletions
diff --git a/src/3rdparty/protocol/input-method.xml b/src/3rdparty/protocol/input-method.xml
deleted file mode 100644
index 70afdcb1d..000000000
--- a/src/3rdparty/protocol/input-method.xml
+++ /dev/null
@@ -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>
diff --git a/src/3rdparty/protocol/text-input-unstable-v2.xml b/src/3rdparty/protocol/text-input-unstable-v2.xml
new file mode 100644
index 000000000..bb366c921
--- /dev/null
+++ b/src/3rdparty/protocol/text-input-unstable-v2.xml
@@ -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>
diff --git a/src/3rdparty/protocol/text.xml b/src/3rdparty/protocol/text.xml
deleted file mode 100644
index 1b5284dc3..000000000
--- a/src/3rdparty/protocol/text.xml
+++ /dev/null
@@ -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>
diff --git a/src/client/client.pro b/src/client/client.pro
index 1219ee345..61404eeb9 100644
--- a/src/client/client.pro
+++ b/src/client/client.pro
@@ -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 \
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
index 7244363cd..a18b9853f 100644
--- a/src/client/qwaylanddisplay.cpp
+++ b/src/client/qwaylanddisplay.cpp
@@ -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
diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h
index 82d87cb92..618e57c59 100644
--- a/src/client/qwaylanddisplay_p.h
+++ b/src/client/qwaylanddisplay_p.h
@@ -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;
diff --git a/src/client/qwaylandinputcontext.cpp b/src/client/qwaylandinputcontext.cpp
index 00f6a4303..aeaf415d2 100644
--- a/src/client/qwaylandinputcontext.cpp
+++ b/src/client/qwaylandinputcontext.cpp
@@ -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)
+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_surface(nullptr)
+ , m_preeditCommit()
+ , m_inputPanelVisible(false)
+ , m_keyboardRectangle()
+ , m_locale()
+ , m_inputDirection(Qt::LayoutDirectionAuto)
+ , m_resetCallback(nullptr)
{
- 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()
- , m_serial(0)
- , m_resetSerial(0)
+QWaylandTextInput::~QWaylandTextInput()
{
+ if (m_resetCallback)
+ wl_callback_destroy(m_resetCallback);
}
-QString QWaylandTextInput::commitString() const
+void QWaylandTextInput::reset()
{
- return m_commit;
+ m_builder.reset();
+ m_preeditCommit = QString();
+ updateState(Qt::ImQueryAll, update_state_reset);
}
-void QWaylandTextInput::reset()
+void QWaylandTextInput::commit()
{
- wl_text_input::reset();
- updateState();
- m_resetSerial = m_serial;
+ if (QObject *o = QGuiApplication::focusObject()) {
+ QInputMethodEvent event;
+ event.setCommitString(m_preeditCommit);
+ QCoreApplication::sendEvent(o, &event);
+ }
+
+ reset();
}
-void QWaylandTextInput::updateState()
+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();
+
+ // 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;
+
+ 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);
+ }
+}
+
+bool QWaylandTextInput::isInputPanelVisible() const
+{
+ 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;
+}
- set_surrounding_text(text, text.leftRef(cursor).toUtf8().size(), text.leftRef(anchor).toUtf8().size());
+void QWaylandTextInput::zwp_text_input_v2_enter(uint32_t serial, ::wl_surface *surface)
+{
+ m_serial = serial;
+ m_surface = surface;
- commit_state(++m_serial);
+ updateState(Qt::ImQueryAll, update_state_enter);
}
-void QWaylandTextInput::text_input_preedit_string(uint32_t serial, const QString &text, const QString &commit)
+void QWaylandTextInput::zwp_text_input_v2_leave(uint32_t serial, ::wl_surface *surface)
{
- Q_UNUSED(serial)
+ 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)
+{
+ m_builder.addPreeditStyling(index, length, style);
+}
+
+void QWaylandTextInput::zwp_text_input_v2_preedit_cursor(int32_t index)
{
- Q_UNUSED(serial);
+ 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::zwp_text_input_v2_cursor_position(int32_t index, int32_t anchor)
+{
+ m_builder.setCursorPosition(index, anchor);
}
-void QWaylandTextInput::text_input_enter(wl_surface *)
+void QWaylandTextInput::zwp_text_input_v2_delete_surrounding_text(uint32_t before_length, uint32_t after_length)
{
- updateState();
- m_resetSerial = m_serial;
+ m_builder.setDeleteSurroundingText(before_length, after_length);
}
-void QWaylandTextInput::text_input_leave()
+void QWaylandTextInput::zwp_text_input_v2_keysym(uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers)
{
- if (!m_commit.isEmpty())
- text_input_commit_string(0, m_commit);
+ if (m_resetCallback) {
+ qCDebug(qLcQpaInputMethods()) << "discard keysym: reset not confirmed";
+ return;
+ }
+
+ if (!QGuiApplication::focusWindow())
+ return;
+
+ 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::text_input_keysym(uint32_t serial, uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers)
+void QWaylandTextInput::zwp_text_input_v2_language(const QString &language)
{
- Q_UNUSED(serial);
- Q_UNUSED(time);
- Q_UNUSED(modifiers);
- if (!QGuiApplication::focusObject())
+ if (m_resetCallback) {
+ qCDebug(qLcQpaInputMethods()) << "discard language: reset not confirmed";
return;
+ }
- // TODO: Convert modifiers to Qt::KeyboardModifiers.
- QKeyEvent event(toQEventType(state), toQtKey(sym), Qt::NoModifier);
- QCoreApplication::sendEvent(qGuiApp->focusWindow(), &event);
+ 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())
- return;
+ qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
- if (!QGuiApplication::focusObject())
+ if (!textInput())
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())
- return;
-
- mTextInput->updateState();
-}
+ qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO << queries;
-void QWaylandInputContext::invokeAction(QInputMethod::Action, int cursorPosition)
-{
- if (!ensureTextInput())
+ if (!QGuiApplication::focusObject() || !textInput())
return;
- mTextInput->invoke_action(0, cursorPosition); // FIXME button, to UTF8 cursor position
+ 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;
+ }
+ }
+
+ 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());
- return;
- }
+ if (!textInput())
+ return QPlatformInputContext::keyboardRect();
- QWindow *window = QGuiApplication::focusWindow();
- if (!window || !window->handle())
- return;
+ return textInput()->keyboardRect();
+}
- struct ::wl_surface *surface = static_cast<QWaylandWindow *>(window->handle())->object();
- mTextInput->activate(mDisplay->defaultInputDevice()->wl_seat(), surface);
+QLocale QWaylandInputContext::locale() const
+{
+ qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
+
+ if (!textInput())
+ return QPlatformInputContext::locale();
+
+ return textInput()->locale();
}
-bool QWaylandInputContext::ensureTextInput()
+Qt::LayoutDirection QWaylandInputContext::inputDirection() const
{
- if (mTextInput)
- return true;
+ 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;
- if (!isValid())
- return false;
+ QWindow *window = QGuiApplication::focusWindow();
- mTextInput.reset(new QWaylandTextInput(mDisplay->textInputManager()->create_text_input()));
- return true;
+ 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);
+ }
}
+QWaylandTextInput *QWaylandInputContext::textInput() const
+{
+ return mDisplay->defaultInputDevice()->textInput();
}
-QT_END_NAMESPACE
+}
+QT_END_NAMESPACE
diff --git a/src/client/qwaylandinputcontext_p.h b/src/client/qwaylandinputcontext_p.h
index cdabfcca4..0429dd14e 100644
--- a/src/client/qwaylandinputcontext_p.h
+++ b/src/client/qwaylandinputcontext_p.h
@@ -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;
};
}
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
index 46c473e70..cf1c7ac44 100644
--- a/src/client/qwaylandinputdevice.cpp
+++ b/src/client/qwaylandinputdevice.cpp
@@ -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.
diff --git a/src/client/qwaylandinputdevice_p.h b/src/client/qwaylandinputdevice_p.h
index 0da45c384..82b9d90c3 100644
--- a/src/client/qwaylandinputdevice_p.h
+++ b/src/client/qwaylandinputdevice_p.h
@@ -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;
diff --git a/src/compositor/compositor.pro b/src/compositor/compositor.pro
index 67c735f98..37f670964 100644
--- a/src/compositor/compositor.pro
+++ b/src/compositor/compositor.pro
@@ -20,8 +20,8 @@ QMAKE_DOCS = $$PWD/doc/qtwaylandcompositor.qdocconf
}
INCLUDEPATH += ../shared
-HEADERS += ../shared/qwaylandmimehelper.h
-SOURCES += ../shared/qwaylandmimehelper.cpp
+HEADERS += ../shared/qwaylandmimehelper.h ../shared/qwaylandinputmethodeventbuilder.h
+SOURCES += ../shared/qwaylandmimehelper.cpp ../shared/qwaylandinputmethodeventbuilder.cpp
include ($$PWD/global/global.pri)
include ($$PWD/wayland_wrapper/wayland_wrapper.pri)
diff --git a/src/compositor/compositor_api/compositor_api.pri b/src/compositor/compositor_api/compositor_api.pri
index 1140efe34..1724ec965 100644
--- a/src/compositor/compositor_api/compositor_api.pri
+++ b/src/compositor/compositor_api/compositor_api.pri
@@ -14,7 +14,6 @@ HEADERS += \
compositor_api/qwaylandpointer_p.h \
compositor_api/qwaylandtouch.h \
compositor_api/qwaylandtouch_p.h \
- compositor_api/qwaylandinputpanel.h \
compositor_api/qwaylandoutput.h \
compositor_api/qwaylanddrag.h \
compositor_api/qwaylandbufferref.h \
@@ -24,6 +23,8 @@ HEADERS += \
compositor_api/qwaylandview_p.h \
compositor_api/qwaylandresource.h \
compositor_api/qwaylandsurfacegrabber.h \
+ compositor_api/qwaylandinputmethodcontrol.h \
+ compositor_api/qwaylandinputmethodcontrol_p.h
SOURCES += \
compositor_api/qwaylandcompositor.cpp \
@@ -33,7 +34,6 @@ SOURCES += \
compositor_api/qwaylandkeyboard.cpp \
compositor_api/qwaylandpointer.cpp \
compositor_api/qwaylandtouch.cpp \
- compositor_api/qwaylandinputpanel.cpp \
compositor_api/qwaylandoutput.cpp \
compositor_api/qwaylanddrag.cpp \
compositor_api/qwaylandbufferref.cpp \
@@ -41,6 +41,7 @@ SOURCES += \
compositor_api/qwaylandview.cpp \
compositor_api/qwaylandresource.cpp \
compositor_api/qwaylandsurfacegrabber.cpp \
+ compositor_api/qwaylandinputmethodcontrol.cpp
QT += core-private
diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp
index 17b089dcf..9bc4f582b 100644
--- a/src/compositor/compositor_api/qwaylandcompositor.cpp
+++ b/src/compositor/compositor_api/qwaylandcompositor.cpp
@@ -85,6 +85,8 @@
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(qLcCompositorInputMethods, "qt.compositor.input.methods")
+
namespace QtWayland {
class WindowSystemEventHandler : public QWindowSystemEventHandler
diff --git a/src/compositor/compositor_api/qwaylandcompositor.h b/src/compositor/compositor_api/qwaylandcompositor.h
index a30786eb2..c03bcc5d1 100644
--- a/src/compositor/compositor_api/qwaylandcompositor.h
+++ b/src/compositor/compositor_api/qwaylandcompositor.h
@@ -44,6 +44,7 @@
#include <QObject>
#include <QImage>
#include <QRect>
+#include <QLoggingCategory>
struct wl_display;
@@ -66,6 +67,8 @@ class QWaylandTouch;
class QWaylandSurfaceGrabber;
class QWaylandBufferRef;
+Q_DECLARE_LOGGING_CATEGORY(qLcCompositorInputMethods)
+
class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandCompositor : public QWaylandObject
{
Q_OBJECT
diff --git a/src/compositor/compositor_api/qwaylandinput.cpp b/src/compositor/compositor_api/qwaylandinput.cpp
index ed1a9c786..ad6cb2369 100644
--- a/src/compositor/compositor_api/qwaylandinput.cpp
+++ b/src/compositor/compositor_api/qwaylandinput.cpp
@@ -38,17 +38,18 @@
#include "qwaylandinput_p.h"
#include "qwaylandcompositor.h"
+#include "qwaylandinputmethodcontrol.h"
#include "qwaylandview.h"
#include <QtWaylandCompositor/QWaylandDrag>
#include <QtWaylandCompositor/QWaylandTouch>
#include <QtWaylandCompositor/QWaylandPointer>
#include <QtWaylandCompositor/QWaylandWlShellSurface>
-#include <QtWaylandCompositor/private/qwlinputmethod_p.h>
#include <QtWaylandCompositor/private/qwaylandinput_p.h>
#include <QtWaylandCompositor/private/qwaylandcompositor_p.h>
#include <QtWaylandCompositor/private/qwldatadevice_p.h>
#include "extensions/qwlqtkey_p.h"
+#include "extensions/qwaylandtextinput.h"
QT_BEGIN_NAMESPACE
@@ -295,11 +296,21 @@ void QWaylandInputDevice::sendFullTouchEvent(QTouchEvent *event)
void QWaylandInputDevice::sendFullKeyEvent(QKeyEvent *event)
{
Q_D(QWaylandInputDevice);
+
if (!keyboardFocus()) {
qWarning("Cannot send key event, no keyboard focus, fix the compositor");
return;
}
+ if (keyboardFocus()->inputMethodControl()->enabled()
+ && event->nativeScanCode() == 0) {
+ QWaylandTextInput *textInput = QWaylandTextInput::findIn(this);
+ if (textInput) {
+ textInput->sendKeyEvent(event);
+ return;
+ }
+ }
+
QtWayland::QtKeyExtensionGlobal *ext = QtWayland::QtKeyExtensionGlobal::findIn(d->compositor);
if (ext && ext->postQtKeyEvent(event, keyboardFocus()))
return;
diff --git a/src/compositor/compositor_api/qwaylandinputmethodcontrol.cpp b/src/compositor/compositor_api/qwaylandinputmethodcontrol.cpp
new file mode 100644
index 000000000..a82990f3d
--- /dev/null
+++ b/src/compositor/compositor_api/qwaylandinputmethodcontrol.cpp
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandinputmethodcontrol.h"
+#include "qwaylandinputmethodcontrol_p.h"
+
+#include "qwaylandcompositor.h"
+#include "qwaylandinput.h"
+#include "qwaylandsurface.h"
+#include "qwaylandview.h"
+#include "qwaylandtextinput.h"
+
+#include <QtGui/QInputMethodEvent>
+
+QWaylandInputMethodControl::QWaylandInputMethodControl(QWaylandSurface *surface)
+ : QObject(*new QWaylandInputMethodControlPrivate(surface), surface)
+{
+ connect(d_func()->compositor, &QWaylandCompositor::defaultInputDeviceChanged,
+ this, &QWaylandInputMethodControl::defaultInputDeviceChanged);
+ connect(d_func()->textInput(), &QWaylandTextInput::surfaceEnabled, this, &QWaylandInputMethodControl::surfaceEnabled);
+ connect(d_func()->textInput(), &QWaylandTextInput::surfaceDisabled, this, &QWaylandInputMethodControl::surfaceDisabled);
+#ifndef QT_NO_IM
+ connect(d_func()->textInput(), &QWaylandTextInput::updateInputMethod, this, &QWaylandInputMethodControl::updateInputMethod);
+#endif
+}
+
+QVariant QWaylandInputMethodControl::inputMethodQuery(Qt::InputMethodQuery query, QVariant argument) const
+{
+ Q_D(const QWaylandInputMethodControl);
+
+ QWaylandTextInput *textInput = d->textInput();
+
+ if (textInput && textInput->focus() == d->surface) {
+ return textInput->inputMethodQuery(query, argument);
+ }
+
+ return QVariant();
+}
+
+void QWaylandInputMethodControl::inputMethodEvent(QInputMethodEvent *event)
+{
+ Q_D(QWaylandInputMethodControl);
+
+ QWaylandTextInput *textInput = d->textInput();
+ if (textInput) {
+ textInput->sendInputMethodEvent(event);
+ } else {
+ event->ignore();
+ }
+}
+
+bool QWaylandInputMethodControl::enabled() const
+{
+ Q_D(const QWaylandInputMethodControl);
+
+ return d->enabled;
+}
+
+void QWaylandInputMethodControl::setEnabled(bool enabled)
+{
+ Q_D(QWaylandInputMethodControl);
+
+ if (d->enabled == enabled)
+ return;
+
+ d->enabled = enabled;
+ emit enabledChanged(enabled);
+#ifndef QT_NO_IM
+ emit updateInputMethod(Qt::ImQueryInput);
+#endif
+}
+
+void QWaylandInputMethodControl::surfaceEnabled(QWaylandSurface *surface)
+{
+ Q_D(QWaylandInputMethodControl);
+
+ if (surface == d->surface)
+ setEnabled(true);
+}
+
+void QWaylandInputMethodControl::surfaceDisabled(QWaylandSurface *surface)
+{
+ Q_D(QWaylandInputMethodControl);
+
+ if (surface == d->surface)
+ setEnabled(false);
+}
+
+void QWaylandInputMethodControl::setSurface(QWaylandSurface *surface)
+{
+ Q_D(QWaylandInputMethodControl);
+
+ if (d->surface == surface)
+ return;
+
+ d->surface = surface;
+
+ QWaylandTextInput *textInput = d->textInput();
+ setEnabled(textInput && textInput->isSurfaceEnabled(d->surface));
+}
+
+void QWaylandInputMethodControl::defaultInputDeviceChanged()
+{
+ Q_D(QWaylandInputMethodControl);
+
+ disconnect(d->textInput(), 0, this, 0);
+
+ d->inputDevice = d->compositor->defaultInputDevice();
+ QWaylandTextInput *textInput = d->textInput();
+
+ connect(textInput, &QWaylandTextInput::surfaceEnabled, this, &QWaylandInputMethodControl::surfaceEnabled);
+ connect(textInput, &QWaylandTextInput::surfaceDisabled, this, &QWaylandInputMethodControl::surfaceDisabled);
+
+ setEnabled(textInput && textInput->isSurfaceEnabled(d->surface));
+}
+
+QWaylandInputMethodControlPrivate::QWaylandInputMethodControlPrivate(QWaylandSurface *surface)
+ : QObjectPrivate()
+ , compositor(surface->compositor())
+ , inputDevice(compositor->defaultInputDevice())
+ , surface(surface)
+ , enabled(false)
+{
+}
+
+QWaylandTextInput *QWaylandInputMethodControlPrivate::textInput() const
+{
+ return QWaylandTextInput::findIn(inputDevice);
+}
diff --git a/src/compositor/compositor_api/qwaylandinputpanel.cpp b/src/compositor/compositor_api/qwaylandinputmethodcontrol.h
index 6f774cd98..f71650294 100644
--- a/src/compositor/compositor_api/qwaylandinputpanel.cpp
+++ b/src/compositor/compositor_api/qwaylandinputmethodcontrol.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
@@ -34,50 +34,51 @@
**
****************************************************************************/
-#include "qwaylandinputpanel.h"
+#ifndef QWAYLANDINPUTMETHODCONTROL_H
+#define QWAYLANDINPUTMETHODCONTROL_H
-#include <QtWaylandCompositor/QWaylandCompositor>
-
-#include <private/qobject_p.h>
-
-#include "qwlinputpanel_p.h"
+#include <QObject>
QT_BEGIN_NAMESPACE
-QWaylandInputPanel::QWaylandInputPanel(QWaylandCompositor *compositor)
- : QWaylandExtensionTemplate(compositor, *new QWaylandInputPanelPrivate(compositor))
-{
-}
+class QWaylandCompositor;
+class QWaylandInputMethodControlPrivate;
+class QWaylandSurface;
+class QInputMethodEvent;
-QWaylandSurface *QWaylandInputPanel::focus() const
+class QWaylandInputMethodControl : public QObject
{
- Q_D(const QWaylandInputPanel);
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWaylandInputMethodControl)
+ Q_DISABLE_COPY(QWaylandInputMethodControl)
- return d->focus();
-}
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+public:
+ explicit QWaylandInputMethodControl(QWaylandSurface *surface);
-bool QWaylandInputPanel::visible() const
-{
- Q_D(const QWaylandInputPanel);
+#ifndef QT_NO_IM
+ QVariant inputMethodQuery(Qt::InputMethodQuery query, QVariant argument) const;
+#endif
- return d->inputPanelVisible();
-}
+ void inputMethodEvent(QInputMethodEvent *event);
-QRect QWaylandInputPanel::cursorRectangle() const
-{
- Q_D(const QWaylandInputPanel);
+ bool enabled() const;
+ void setEnabled(bool enabled);
- return d->cursorRectangle();
-}
+ void setSurface(QWaylandSurface *surface);
-const struct wl_interface *QWaylandInputPanel::interface()
-{
- return QWaylandInputPanelPrivate::interface();
-}
+Q_SIGNALS:
+ void enabledChanged(bool enabled);
+#ifndef QT_NO_IM
+ void updateInputMethod(Qt::InputMethodQueries queries);
+#endif
-QByteArray QWaylandInputPanel::interfaceName()
-{
- return QWaylandInputPanelPrivate::interfaceName();
-}
+private:
+ void defaultInputDeviceChanged();
+ void surfaceEnabled(QWaylandSurface *surface);
+ void surfaceDisabled(QWaylandSurface *surface);
+};
QT_END_NAMESPACE
+
+#endif // QWAYLANDINPUTMETHODCONTROL_H
diff --git a/src/compositor/compositor_api/qwaylandinputpanel.h b/src/compositor/compositor_api/qwaylandinputmethodcontrol_p.h
index d29743140..a687e5299 100644
--- a/src/compositor/compositor_api/qwaylandinputpanel.h
+++ b/src/compositor/compositor_api/qwaylandinputmethodcontrol_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
@@ -34,45 +34,47 @@
**
****************************************************************************/
-#ifndef QWAYLANDINPUTPANEL_H
-#define QWAYLANDINPUTPANEL_H
+#ifndef QWAYLANDINPUTMETHODCONTROL_P_H
+#define QWAYLANDINPUTMETHODCONTROL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include <QtWaylandCompositor/qwaylandexport.h>
-#include <QtWaylandCompositor/qwaylandextension.h>
+#include <QtWaylandCompositor/qwaylandinputmethodcontrol.h>
-#include <QObject>
-#include <QRect>
+#include <QtCore/private/qobject_p.h>
QT_BEGIN_NAMESPACE
class QWaylandCompositor;
-class QWaylandInputPanelPrivate;
+class QWaylandInputDevice;
class QWaylandSurface;
+class QWaylandTextInput;
-class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandInputPanel : public QWaylandExtensionTemplate<QWaylandInputPanel>
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandInputMethodControlPrivate : public QObjectPrivate
{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QWaylandInputPanel)
-
- Q_PROPERTY(QWaylandSurface* focus READ focus NOTIFY focusChanged)
- Q_PROPERTY(bool visible READ visible NOTIFY visibleChanged)
- Q_PROPERTY(QRect cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged)
+ Q_DECLARE_PUBLIC(QWaylandInputMethodControl)
public:
- explicit QWaylandInputPanel(QWaylandCompositor *compositor);
+ explicit QWaylandInputMethodControlPrivate(QWaylandSurface *surface);
- QWaylandSurface *focus() const;
- bool visible() const;
- QRect cursorRectangle() const;
+ QWaylandTextInput *textInput() const;
- static const struct wl_interface *interface();
- static QByteArray interfaceName();
-Q_SIGNALS:
- void focusChanged();
- void visibleChanged();
- void cursorRectangleChanged();
+ QWaylandCompositor *compositor;
+ QWaylandInputDevice *inputDevice;
+ QWaylandSurface *surface;
+ bool enabled;
};
QT_END_NAMESPACE
-#endif // QWAYLANDINPUTPANEL_H
+#endif // QWAYLANDINPUTMETHODCONTROL_P_H
diff --git a/src/compositor/compositor_api/qwaylandquickitem.cpp b/src/compositor/compositor_api/qwaylandquickitem.cpp
index 8fd759bda..bee12b4a5 100644
--- a/src/compositor/compositor_api/qwaylandquickitem.cpp
+++ b/src/compositor/compositor_api/qwaylandquickitem.cpp
@@ -37,6 +37,8 @@
#include "qwaylandquickitem.h"
#include "qwaylandquickitem_p.h"
#include "qwaylandquicksurface.h"
+#include "qwaylandinputmethodcontrol.h"
+#include "qwaylandtextinput.h"
#include <QtWaylandCompositor/qwaylandcompositor.h>
#include <QtWaylandCompositor/qwaylandinput.h>
#include <QtWaylandCompositor/qwaylandbufferref.h>
@@ -54,6 +56,7 @@
#include <wayland-server.h>
#include <QThread>
+
QT_BEGIN_NAMESPACE
QMutex *QWaylandQuickItemPrivate::mutex = 0;
@@ -459,6 +462,21 @@ void QWaylandQuickItem::mouseUngrabEvent()
}
}
+#ifndef QT_NO_IM
+/*!
+ * \internal
+ */
+void QWaylandQuickItem::inputMethodEvent(QInputMethodEvent *event)
+{
+ Q_D(QWaylandQuickItem);
+ if (d->shouldSendInputEvents()) {
+ d->oldSurface->inputMethodControl()->inputMethodEvent(event);
+ } else {
+ event->ignore();
+ }
+}
+#endif
+
/*!
* \internal
*/
@@ -480,6 +498,9 @@ void QWaylandQuickItem::handleSurfaceChanged()
disconnect(d->oldSurface, &QWaylandSurface::sizeChanged, this, &QWaylandQuickItem::updateSize);
disconnect(d->oldSurface, &QWaylandSurface::configure, this, &QWaylandQuickItem::updateBuffer);
disconnect(d->oldSurface, &QWaylandSurface::redraw, this, &QQuickItem::update);
+#ifndef QT_NO_IM
+ disconnect(d->oldSurface->inputMethodControl(), &QWaylandInputMethodControl::updateInputMethod, this, &QWaylandQuickItem::updateInputMethod);
+#endif
}
if (QWaylandSurface *newSurface = d->view->surface()) {
connect(newSurface, &QWaylandSurface::mappedChanged, this, &QWaylandQuickItem::surfaceMappedChanged);
@@ -487,6 +508,9 @@ void QWaylandQuickItem::handleSurfaceChanged()
connect(newSurface, &QWaylandSurface::sizeChanged, this, &QWaylandQuickItem::updateSize);
connect(newSurface, &QWaylandSurface::configure, this, &QWaylandQuickItem::updateBuffer);
connect(newSurface, &QWaylandSurface::redraw, this, &QQuickItem::update);
+#ifndef QT_NO_IM
+ connect(newSurface->inputMethodControl(), &QWaylandInputMethodControl::updateInputMethod, this, &QWaylandQuickItem::updateInputMethod);
+#endif
if (d->sizeFollowsSurface) {
setWidth(newSurface->size().width());
setHeight(newSurface->size().height());
@@ -502,6 +526,9 @@ void QWaylandQuickItem::handleSurfaceChanged()
}
surfaceChangedEvent(d->view->surface(), d->oldSurface);
d->oldSurface = d->view->surface();
+#ifndef QT_NO_IM
+ updateInputMethod(Qt::ImQueryInput);
+#endif
}
/*!
@@ -510,7 +537,7 @@ void QWaylandQuickItem::handleSurfaceChanged()
*/
void QWaylandQuickItem::takeFocus(QWaylandInputDevice *device)
{
- setFocus(true);
+ forceActiveFocus();
if (!surface())
return;
@@ -520,6 +547,9 @@ void QWaylandQuickItem::takeFocus(QWaylandInputDevice *device)
target = compositor()->defaultInputDevice();
}
target->setKeyboardFocus(surface());
+ QWaylandTextInput *textInput = QWaylandTextInput::findIn(target);
+ if (textInput)
+ textInput->setFocus(surface());
}
/*!
@@ -632,6 +662,23 @@ void QWaylandQuickItem::setSizeFollowsSurface(bool sizeFollowsSurface)
emit sizeFollowsSurfaceChanged();
}
+#ifndef QT_NO_IM
+QVariant QWaylandQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const
+{
+ return inputMethodQuery(query, QVariant());
+}
+
+QVariant QWaylandQuickItem::inputMethodQuery(Qt::InputMethodQuery query, QVariant argument) const
+{
+ Q_D(const QWaylandQuickItem);
+
+ if (query == Qt::ImEnabled)
+ return QVariant((flags() & ItemAcceptsInputMethod) != 0);
+
+ return d->oldSurface->inputMethodControl()->inputMethodQuery(query, argument);
+}
+#endif
+
/*!
\qmlproperty bool QtWayland::QWaylandSurfaceItem::paintEnabled
@@ -698,6 +745,17 @@ void QWaylandQuickItem::beforeSync()
}
}
+#ifndef QT_NO_IM
+void QWaylandQuickItem::updateInputMethod(Qt::InputMethodQueries queries)
+{
+ Q_D(QWaylandQuickItem);
+
+ setFlag(QQuickItem::ItemAcceptsInputMethod,
+ d->oldSurface ? d->oldSurface->inputMethodControl()->enabled() : false);
+ QQuickItem::updateInputMethod(queries | Qt::ImEnabled);
+}
+#endif
+
QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
Q_D(QWaylandQuickItem);
diff --git a/src/compositor/compositor_api/qwaylandquickitem.h b/src/compositor/compositor_api/qwaylandquickitem.h
index 81ea5213b..9dab65acf 100644
--- a/src/compositor/compositor_api/qwaylandquickitem.h
+++ b/src/compositor/compositor_api/qwaylandquickitem.h
@@ -99,6 +99,11 @@ public:
bool sizeFollowsSurface() const;
void setSizeFollowsSurface(bool sizeFollowsSurface);
+#ifndef QT_NO_IM
+ QVariant inputMethodQuery(Qt::InputMethodQuery query) const Q_DECL_OVERRIDE;
+ Q_INVOKABLE QVariant inputMethodQuery(Qt::InputMethodQuery query, QVariant argument) const;
+#endif
+
protected:
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
@@ -114,6 +119,10 @@ protected:
void touchEvent(QTouchEvent *event) Q_DECL_OVERRIDE;
void mouseUngrabEvent() Q_DECL_OVERRIDE;
+#ifndef QT_NO_IM
+ void inputMethodEvent(QInputMethodEvent *event) Q_DECL_OVERRIDE;
+#endif
+
virtual void surfaceChangedEvent(QWaylandSurface *newSurface, QWaylandSurface *oldSurface);
public Q_SLOTS:
virtual void takeFocus(QWaylandInputDevice *device = 0);
@@ -129,6 +138,9 @@ private Q_SLOTS:
void updateBuffer(bool hasBuffer);
void updateWindow();
void beforeSync();
+#ifndef QT_NO_IM
+ void updateInputMethod(Qt::InputMethodQueries queries);
+#endif
Q_SIGNALS:
void surfaceChanged();
diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp
index 97e4b6a80..3a16ed27a 100644
--- a/src/compositor/compositor_api/qwaylandsurface.cpp
+++ b/src/compositor/compositor_api/qwaylandsurface.cpp
@@ -43,6 +43,7 @@
#include "wayland_wrapper/qwlregion_p.h"
#include "extensions/qwlextendedsurface_p.h"
+#include "qwaylandinputmethodcontrol_p.h"
#include <QtWaylandCompositor/QWaylandCompositor>
#include <QtWaylandCompositor/QWaylandClient>
@@ -124,13 +125,13 @@ QWaylandSurfacePrivate::QWaylandSurfacePrivate()
, client(Q_NULLPTR)
, buffer(0)
, role(0)
- , inputPanelSurface(0)
, inputRegion(infiniteRegion())
, isCursorSurface(false)
, destroyed(false)
, mapped(false)
, isInitialized(false)
, contentOrientation(Qt::PrimaryOrientation)
+ , inputMethodControl(Q_NULLPTR)
, subsurface(0)
{
pending.buffer = 0;
@@ -426,6 +427,7 @@ void QWaylandSurface::initialize(QWaylandCompositor *compositor, QWaylandClient
d->client = client;
d->init(client->client(), id, version);
d->isInitialized = true;
+ d->inputMethodControl = new QWaylandInputMethodControl(this);
#ifndef QT_NO_DEBUG
QWaylandSurfacePrivate::removeUninitializedSurface(d);
#endif
@@ -588,16 +590,6 @@ void QWaylandSurface::sendFrameCallbacks()
}
/*!
- * Returns true if the QWaylandSurface has an input panel surface. Otherwise returns false.
- */
-bool QWaylandSurface::hasInputPanelSurface() const
-{
- Q_D(const QWaylandSurface);
-
- return d->inputPanelSurface != 0;
-}
-
-/*!
* Returns true if the QWaylandSurface's input region contains the point \a p.
* Otherwise returns false.
*/
@@ -660,6 +652,12 @@ bool QWaylandSurface::isCursorSurface() const
return d->isCursorSurface;
}
+QWaylandInputMethodControl *QWaylandSurface::inputMethodControl() const
+{
+ Q_D(const QWaylandSurface);
+ return d->inputMethodControl;
+}
+
/*!
* Updates the surface with the compositor's retained clipboard selection. While this
* is done automatically when the surface receives keyboard focus, this function is
diff --git a/src/compositor/compositor_api/qwaylandsurface.h b/src/compositor/compositor_api/qwaylandsurface.h
index a782e5bae..6abdbdef5 100644
--- a/src/compositor/compositor_api/qwaylandsurface.h
+++ b/src/compositor/compositor_api/qwaylandsurface.h
@@ -59,6 +59,7 @@ class QWaylandCompositor;
class QWaylandBufferRef;
class QWaylandView;
class QWaylandSurfaceOp;
+class QWaylandInputMethodControl;
class QWaylandSurfaceRole
{
@@ -112,8 +113,6 @@ public:
QWaylandCompositor *compositor() const;
- bool hasInputPanelSurface() const;
-
bool inputRegionContains(const QPoint &p) const;
Q_INVOKABLE void destroy();
@@ -133,6 +132,8 @@ public:
void markAsCursorSurface(bool cursorSurface);
bool isCursorSurface() const;
+ QWaylandInputMethodControl *inputMethodControl() const;
+
public Q_SLOTS:
void updateSelection();
diff --git a/src/compositor/compositor_api/qwaylandsurface_p.h b/src/compositor/compositor_api/qwaylandsurface_p.h
index 635820931..d8b289c63 100644
--- a/src/compositor/compositor_api/qwaylandsurface_p.h
+++ b/src/compositor/compositor_api/qwaylandsurface_p.h
@@ -56,7 +56,6 @@
#include <QtWaylandCompositor/qwaylandsurface.h>
#include <QtWaylandCompositor/qwaylandbufferref.h>
-#include <QtWaylandCompositor/private/qwlinputpanelsurface_p.h>
#include <QtWaylandCompositor/private/qwlregion_p.h>
#include <QtCore/QVector>
@@ -78,6 +77,7 @@ class QWaylandCompositor;
class QWaylandSurface;
class QWaylandView;
class QWaylandSurfaceInterface;
+class QWaylandInputMethodControl;
namespace QtWayland {
class FrameCallback;
@@ -105,8 +105,6 @@ public:
void notifyViewsAboutDestruction();
- void setInputPanelSurface(QtWayland::InputPanelSurface *ips) { inputPanelSurface = ips; }
-
#ifndef QT_NO_DEBUG
static void addUninitializedSurface(QWaylandSurfacePrivate *surface);
static void removeUninitializedSurface(QWaylandSurfacePrivate *surface);
@@ -161,8 +159,6 @@ public: //member variables
QList<QtWayland::FrameCallback *> pendingFrameCallbacks;
QList<QtWayland::FrameCallback *> frameCallbacks;
- QtWayland::InputPanelSurface *inputPanelSurface;
-
QRegion inputRegion;
QRegion opaqueRegion;
@@ -175,6 +171,7 @@ public: //member variables
bool isInitialized;
Qt::ScreenOrientation contentOrientation;
QWindow::Visibility visibility;
+ QWaylandInputMethodControl *inputMethodControl;
class Subsurface : public QtWaylandServer::wl_subsurface
{
diff --git a/src/compositor/extensions/extensions.pri b/src/compositor/extensions/extensions.pri
index 03be3905e..1d34803f0 100644
--- a/src/compositor/extensions/extensions.pri
+++ b/src/compositor/extensions/extensions.pri
@@ -4,8 +4,7 @@ WAYLANDSERVERSOURCES += \
../extensions/touch-extension.xml \
../extensions/qtkey-extension.xml \
../extensions/windowmanager.xml \
- ../3rdparty/protocol/input-method.xml \
- ../3rdparty/protocol/text.xml \
+ ../3rdparty/protocol/text-input-unstable-v2.xml \
../3rdparty/protocol/xdg-shell.xml \
HEADERS += \
@@ -14,14 +13,12 @@ HEADERS += \
extensions/qwlqtkey_p.h \
extensions/qwaylandwlshell.h \
extensions/qwaylandwlshell_p.h \
+ extensions/qwaylandtextinput.h \
+ extensions/qwaylandtextinput_p.h \
+ extensions/qwaylandtextinputmanager.h \
+ extensions/qwaylandtextinputmanager_p.h \
extensions/qwaylandwindowmanagerextension.h \
extensions/qwaylandwindowmanagerextension_p.h \
- extensions/qwltextinput_p.h \
- extensions/qwltextinputmanager_p.h \
- extensions/qwlinputpanel_p.h \
- extensions/qwlinputpanelsurface_p.h \
- extensions/qwlinputmethod_p.h \
- extensions/qwlinputmethodcontext_p.h \
extensions/qwaylandxdgshell.h \
extensions/qwaylandxdgshell_p.h \
@@ -30,13 +27,9 @@ SOURCES += \
extensions/qwlqttouch.cpp \
extensions/qwlqtkey.cpp \
extensions/qwaylandwlshell.cpp \
+ extensions/qwaylandtextinput.cpp \
+ extensions/qwaylandtextinputmanager.cpp \
extensions/qwaylandwindowmanagerextension.cpp \
- extensions/qwltextinput.cpp \
- extensions/qwltextinputmanager.cpp \
- extensions/qwlinputpanel.cpp \
- extensions/qwlinputpanelsurface.cpp \
- extensions/qwlinputmethod.cpp \
- extensions/qwlinputmethodcontext.cpp \
extensions/qwaylandxdgshell.cpp \
qtHaveModule(quick) {
diff --git a/src/compositor/extensions/qwaylandtextinput.cpp b/src/compositor/extensions/qwaylandtextinput.cpp
new file mode 100644
index 000000000..31166ddb2
--- /dev/null
+++ b/src/compositor/extensions/qwaylandtextinput.cpp
@@ -0,0 +1,591 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandtextinput.h"
+#include "qwaylandtextinput_p.h"
+
+#include <QtWaylandCompositor/QWaylandCompositor>
+#include <QtWaylandCompositor/private/qwaylandinput_p.h>
+
+#include "qwaylandsurface.h"
+#include "qwaylandview.h"
+#include "qwaylandxkb.h"
+#include "qwaylandinputmethodeventbuilder.h"
+
+#include <QGuiApplication>
+#include <QInputMethodEvent>
+
+QT_BEGIN_NAMESPACE
+
+QWaylandTextInputClientState::QWaylandTextInputClientState()
+ : hints(0)
+ , cursorRectangle()
+ , surroundingText()
+ , cursorPosition(0)
+ , anchorPosition(0)
+ , preferredLanguage()
+ , changedState()
+{
+}
+
+Qt::InputMethodQueries QWaylandTextInputClientState::updatedQueries(const QWaylandTextInputClientState &other) const
+{
+ Qt::InputMethodQueries queries;
+
+ if (hints != other.hints)
+ queries |= Qt::ImHints;
+ if (cursorRectangle != other.cursorRectangle)
+ queries |= Qt::ImCursorRectangle;
+ if (surroundingText != other.surroundingText)
+ queries |= Qt::ImSurroundingText | Qt::ImCurrentSelection;
+ if (cursorPosition != other.cursorPosition)
+ queries |= Qt::ImCursorPosition | Qt::ImCurrentSelection;
+ if (anchorPosition != other.anchorPosition)
+ queries |= Qt::ImAnchorPosition | Qt::ImCurrentSelection;
+ if (preferredLanguage != other.preferredLanguage)
+ queries |= Qt::ImPreferredLanguage;
+
+ return queries;
+}
+
+Qt::InputMethodQueries QWaylandTextInputClientState::mergeChanged(const QWaylandTextInputClientState &other) {
+ Qt::InputMethodQueries queries;
+
+ if ((other.changedState & Qt::ImHints) && hints != other.hints) {
+ hints = other.hints;
+ queries |= Qt::ImHints;
+ }
+
+ if ((other.changedState & Qt::ImCursorRectangle) && cursorRectangle != other.cursorRectangle) {
+ cursorRectangle = other.cursorRectangle;
+ queries |= Qt::ImCursorRectangle;
+ }
+
+ if ((other.changedState & Qt::ImSurroundingText) && surroundingText != other.surroundingText) {
+ surroundingText = other.surroundingText;
+ queries |= Qt::ImSurroundingText | Qt::ImCurrentSelection;
+ }
+
+ if ((other.changedState & Qt::ImCursorPosition) && cursorPosition != other.cursorPosition) {
+ cursorPosition = other.cursorPosition;
+ queries |= Qt::ImCursorPosition | Qt::ImCurrentSelection;
+ }
+
+ if ((other.changedState & Qt::ImAnchorPosition) && anchorPosition != other.anchorPosition) {
+ anchorPosition = other.anchorPosition;
+ queries |= Qt::ImAnchorPosition | Qt::ImCurrentSelection;
+ }
+
+ if ((other.changedState & Qt::ImPreferredLanguage) && preferredLanguage != other.preferredLanguage) {
+ preferredLanguage = other.preferredLanguage;
+ queries |= Qt::ImPreferredLanguage;
+ }
+
+ return queries;
+}
+
+QWaylandTextInputPrivate::QWaylandTextInputPrivate(QWaylandCompositor *compositor)
+ : QWaylandExtensionTemplatePrivate()
+ , QtWaylandServer::zwp_text_input_v2()
+ , compositor(compositor)
+ , focus(nullptr)
+ , focusResource(nullptr)
+ , focusDestroyListener()
+ , inputPanelVisible(false)
+ , currentState(new QWaylandTextInputClientState)
+ , pendingState(new QWaylandTextInputClientState)
+ , serial(0)
+ , enabledSurfaces()
+{
+}
+
+void QWaylandTextInputPrivate::sendInputMethodEvent(QInputMethodEvent *event)
+{
+ if (!focusResource || !focusResource->handle)
+ return;
+
+ if (event->replacementLength() > 0 || event->replacementStart() != 0) {
+ if (event->replacementStart() <= 0 && (event->replacementLength() >= -event->replacementStart())) {
+ const int selectionStart = qMin(currentState->cursorPosition, currentState->anchorPosition);
+ const int selectionEnd = qMax(currentState->cursorPosition, currentState->anchorPosition);
+ const int before = currentState->surroundingText.midRef(selectionStart + event->replacementStart(), -event->replacementStart()).toUtf8().size();
+ const int after = currentState->surroundingText.midRef(selectionEnd, event->replacementLength() + event->replacementStart()).toUtf8().size();
+ send_delete_surrounding_text(focusResource->handle, before, after);
+ } else {
+ // TODO: Implement this case
+ qWarning() << "Not yet supported case of replacement. Start:" << event->replacementStart() << "length:" << event->replacementLength();
+ }
+ }
+ foreach (const QInputMethodEvent::Attribute &attribute, event->attributes()) {
+ if (attribute.type == QInputMethodEvent::Selection) {
+ const int cursorAfterCommit = qMin(currentState->cursorPosition, currentState->anchorPosition) + event->replacementStart() + event->commitString().length();
+ QString textAfterCommit = currentState->surroundingText;
+ textAfterCommit.remove(qMin(currentState->cursorPosition, currentState->anchorPosition),
+ qAbs(currentState->cursorPosition - currentState->anchorPosition));
+ textAfterCommit.replace(qMin(currentState->cursorPosition, currentState->anchorPosition) + event->replacementStart(),
+ event->replacementLength(), event->commitString());
+
+ int cursor = textAfterCommit.midRef(qMin(attribute.start, cursorAfterCommit), qAbs(attribute.start - cursorAfterCommit)).toUtf8().size();
+ int anchor = textAfterCommit.midRef(qMin(attribute.length, cursorAfterCommit), qAbs(attribute.length - cursorAfterCommit)).toUtf8().size();
+ send_cursor_position(focusResource->handle,
+ attribute.start < cursorAfterCommit ? -cursor : cursor,
+ attribute.start < cursorAfterCommit ? -anchor : anchor);
+ }
+ }
+ send_commit_string(focusResource->handle, event->commitString());
+ foreach (const QInputMethodEvent::Attribute &attribute, event->attributes()) {
+ if (attribute.type == QInputMethodEvent::Cursor) {
+ int index = event->preeditString().leftRef(attribute.start).toUtf8().size();
+ send_preedit_cursor(focusResource->handle, index);
+ } else if (attribute.type == QInputMethodEvent::TextFormat) {
+ int start = currentState->surroundingText.leftRef(attribute.start).toUtf8().size();
+ int end = currentState->surroundingText.leftRef(attribute.start + attribute.length).toUtf8().size();
+ // TODO add support for different stylesQWaylandTextInput
+ send_preedit_styling(focusResource->handle, start, end - start, preedit_style_default);
+ }
+ }
+ send_preedit_string(focusResource->handle, event->preeditString(), event->preeditString());
+}
+
+void QWaylandTextInputPrivate::sendKeyEvent(QKeyEvent *event)
+{
+ if (!focusResource || !focusResource->handle)
+ return;
+
+ // TODO add support for modifiers
+
+ foreach (xkb_keysym_t keysym, QWaylandXkb::toKeysym(event)) {
+ send_keysym(focusResource->handle, event->timestamp(), keysym,
+ event->type() == QEvent::KeyPress ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED,
+ 0);
+ }
+}
+
+void QWaylandTextInputPrivate::sendInputPanelState()
+{
+ if (!focusResource || !focusResource->handle)
+ return;
+
+ QInputMethod *inputMethod = qApp->inputMethod();
+ const QRectF& keyboardRect = inputMethod->keyboardRectangle();
+ const QRectF& sceneInputRect = inputMethod->inputItemTransform().mapRect(inputMethod->inputItemRectangle());
+ const QRectF& localRect = sceneInputRect.intersected(keyboardRect).translated(-sceneInputRect.topLeft());
+
+ send_input_panel_state(focusResource->handle,
+ inputMethod->isVisible() ? input_panel_visibility_visible : input_panel_visibility_hidden,
+ localRect.x(), localRect.y(), localRect.width(), localRect.height());
+}
+
+void QWaylandTextInputPrivate::sendTextDirection()
+{
+ if (!focusResource || !focusResource->handle)
+ return;
+
+ const Qt::LayoutDirection direction = qApp->inputMethod()->inputDirection();
+ send_text_direction(focusResource->handle,
+ (direction == Qt::LeftToRight) ? text_direction_ltr :
+ (direction == Qt::RightToLeft) ? text_direction_rtl : text_direction_auto);
+}
+
+void QWaylandTextInputPrivate::sendLocale()
+{
+ if (!focusResource || !focusResource->handle)
+ return;
+
+ const QLocale locale = qApp->inputMethod()->locale();
+ send_language(focusResource->handle, locale.bcp47Name());
+}
+
+QVariant QWaylandTextInputPrivate::inputMethodQuery(Qt::InputMethodQuery property, QVariant argument) const
+{
+ switch (property) {
+ case Qt::ImHints:
+ return QVariant(static_cast<int>(currentState->hints));
+ case Qt::ImCursorRectangle:
+ return currentState->cursorRectangle;
+ case Qt::ImFont:
+ // Not supported
+ return QVariant();
+ case Qt::ImCursorPosition:
+ return currentState->cursorPosition;
+ case Qt::ImSurroundingText:
+ return currentState->surroundingText;
+ case Qt::ImCurrentSelection:
+ return currentState->surroundingText.mid(qMin(currentState->cursorPosition, currentState->anchorPosition),
+ qAbs(currentState->anchorPosition - currentState->cursorPosition));
+ case Qt::ImMaximumTextLength:
+ // Not supported
+ return QVariant();
+ case Qt::ImAnchorPosition:
+ return currentState->anchorPosition;
+ case Qt::ImAbsolutePosition:
+ // We assume the surrounding text is our whole document for now
+ return currentState->cursorPosition;
+ case Qt::ImTextAfterCursor:
+ if (argument.isValid())
+ return currentState->surroundingText.mid(currentState->cursorPosition, argument.toInt());
+ return currentState->surroundingText.mid(currentState->cursorPosition);
+ case Qt::ImTextBeforeCursor:
+ if (argument.isValid())
+ return currentState->surroundingText.left(currentState->cursorPosition).right(argument.toInt());
+ return currentState->surroundingText.left(currentState->cursorPosition);
+ case Qt::ImPreferredLanguage:
+ return currentState->preferredLanguage;
+
+ default:
+ return QVariant();
+ }
+}
+
+void QWaylandTextInputPrivate::setFocus(QWaylandSurface *surface)
+{
+ Q_Q(QWaylandTextInput);
+
+ if (focusResource && focus != surface) {
+ uint32_t serial = compositor->nextSerial();
+ send_leave(focusResource->handle, serial, focus->resource());
+ focusDestroyListener.reset();
+ }
+
+ Resource *resource = surface ? resourceMap().value(surface->waylandClient()) : 0;
+
+ if (resource && (focus != surface || focusResource != resource)) {
+ uint32_t serial = compositor->nextSerial();
+ currentState.reset(new QWaylandTextInputClientState);
+ pendingState.reset(new QWaylandTextInputClientState);
+ send_enter(resource->handle, serial, surface->resource());
+ focusResource = resource;
+ sendInputPanelState();
+ sendLocale();
+ sendTextDirection();
+ focusDestroyListener.listenForDestruction(surface->resource());
+ if (inputPanelVisible && q->isSurfaceEnabled(surface))
+ qApp->inputMethod()->show();
+ }
+
+ focusResource = resource;
+ focus = surface;
+}
+
+void QWaylandTextInputPrivate::zwp_text_input_v2_bind_resource(Resource *resource)
+{
+ send_modifiers_map(resource->handle, QByteArray(""));
+}
+
+void QWaylandTextInputPrivate::zwp_text_input_v2_destroy_resource(Resource *resource)
+{
+ if (focusResource == resource)
+ focusResource = 0;
+}
+
+void QWaylandTextInputPrivate::zwp_text_input_v2_destroy(Resource *resource)
+{
+ wl_resource_destroy(resource->handle);
+}
+
+void QWaylandTextInputPrivate::zwp_text_input_v2_enable(Resource *resource, wl_resource *surface)
+{
+ Q_Q(QWaylandTextInput);
+
+ QWaylandSurface *s = QWaylandSurface::fromResource(surface);
+ enabledSurfaces.insert(resource, s);
+ emit q->surfaceEnabled(s);
+}
+
+void QWaylandTextInputPrivate::zwp_text_input_v2_disable(QtWaylandServer::zwp_text_input_v2::Resource *resource, wl_resource *)
+{
+ Q_Q(QWaylandTextInput);
+
+ QWaylandSurface *s = enabledSurfaces.take(resource);
+ emit q->surfaceDisabled(s);
+}
+
+void QWaylandTextInputPrivate::zwp_text_input_v2_show_input_panel(Resource *)
+{
+ inputPanelVisible = true;
+
+ qApp->inputMethod()->show();
+}
+
+void QWaylandTextInputPrivate::zwp_text_input_v2_hide_input_panel(Resource *)
+{
+ inputPanelVisible = false;
+
+ qApp->inputMethod()->hide();
+}
+
+void QWaylandTextInputPrivate::zwp_text_input_v2_set_cursor_rectangle(Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
+{
+ if (resource != focusResource)
+ return;
+
+ pendingState->cursorRectangle = QRect(x, y, width, height);
+
+ pendingState->changedState |= Qt::ImCursorRectangle;
+}
+
+void QWaylandTextInputPrivate::zwp_text_input_v2_update_state(Resource *resource, uint32_t serial, uint32_t flags)
+{
+ Q_Q(QWaylandTextInput);
+
+ qCDebug(qLcCompositorInputMethods) << "update_state" << serial << flags;
+
+ if (resource != focusResource)
+ return;
+
+ if (flags == update_state_reset || flags == update_state_enter) {
+ qCDebug(qLcCompositorInputMethods) << "QInputMethod::reset()";
+ qApp->inputMethod()->reset();
+ }
+
+ this->serial = serial;
+
+ Qt::InputMethodQueries queries;
+ if (flags == update_state_change) {
+ queries = currentState->mergeChanged(*pendingState.data());
+ } else {
+ queries = pendingState->updatedQueries(*currentState.data());
+ currentState.swap(pendingState);
+ }
+
+ pendingState.reset(new QWaylandTextInputClientState);
+
+ if (queries) {
+ qCDebug(qLcCompositorInputMethods) << "QInputMethod::update()" << queries;
+
+ emit q->updateInputMethod(queries);
+ }
+}
+
+void QWaylandTextInputPrivate::zwp_text_input_v2_set_content_type(Resource *resource, uint32_t hint, uint32_t purpose)
+{
+ if (resource != focusResource)
+ return;
+
+ pendingState->hints = 0;
+
+ if ((hint & content_hint_auto_completion) == 0
+ && (hint & content_hint_auto_correction) == 0)
+ pendingState->hints |= Qt::ImhNoPredictiveText;
+ if ((hint & content_hint_auto_capitalization) == 0)
+ pendingState->hints |= Qt::ImhNoAutoUppercase;
+ if ((hint & content_hint_lowercase) != 0)
+ pendingState->hints |= Qt::ImhPreferLowercase;
+ if ((hint & content_hint_uppercase) != 0)
+ pendingState->hints |= Qt::ImhPreferUppercase;
+ if ((hint & content_hint_hidden_text) != 0)
+ pendingState->hints |= Qt::ImhHiddenText;
+ if ((hint & content_hint_sensitive_data) != 0)
+ pendingState->hints |= Qt::ImhSensitiveData;
+ if ((hint & content_hint_latin) != 0)
+ pendingState->hints |= Qt::ImhLatinOnly;
+ if ((hint & content_hint_multiline) != 0)
+ pendingState->hints |= Qt::ImhMultiLine;
+
+ switch (purpose) {
+ case content_purpose_normal:
+ break;
+ case content_purpose_alpha:
+ pendingState->hints |= Qt::ImhUppercaseOnly | Qt::ImhLowercaseOnly;
+ break;
+ case content_purpose_digits:
+ pendingState->hints |= Qt::ImhDigitsOnly;
+ break;
+ case content_purpose_number:
+ pendingState->hints |= Qt::ImhFormattedNumbersOnly;
+ break;
+ case content_purpose_phone:
+ pendingState->hints |= Qt::ImhDialableCharactersOnly;
+ break;
+ case content_purpose_url:
+ pendingState->hints |= Qt::ImhUrlCharactersOnly;
+ break;
+ case content_purpose_email:
+ pendingState->hints |= Qt::ImhEmailCharactersOnly;
+ break;
+ case content_purpose_name:
+ case content_purpose_password:
+ break;
+ case content_purpose_date:
+ pendingState->hints |= Qt::ImhDate;
+ break;
+ case content_purpose_time:
+ pendingState->hints |= Qt::ImhTime;
+ break;
+ case content_purpose_datetime:
+ pendingState->hints |= Qt::ImhDate | Qt::ImhTime;
+ break;
+ case content_purpose_terminal:
+ default:
+ break;
+ }
+
+ pendingState->changedState |= Qt::ImHints;
+}
+
+void QWaylandTextInputPrivate::zwp_text_input_v2_set_preferred_language(Resource *resource, const QString &language)
+{
+ if (resource != focusResource)
+ return;
+
+ pendingState->preferredLanguage = language;
+
+ pendingState->changedState |= Qt::ImPreferredLanguage;
+}
+
+void QWaylandTextInputPrivate::zwp_text_input_v2_set_surrounding_text(Resource *resource, const QString &text, int32_t cursor, int32_t anchor)
+{
+ if (resource != focusResource)
+ return;
+
+ pendingState->surroundingText = text;
+ pendingState->cursorPosition = QWaylandInputMethodEventBuilder::indexFromWayland(text, cursor);
+ pendingState->anchorPosition = QWaylandInputMethodEventBuilder::indexFromWayland(text, anchor);
+
+ pendingState->changedState |= Qt::ImSurroundingText | Qt::ImCursorPosition | Qt::ImAnchorPosition;
+}
+
+QWaylandTextInput::QWaylandTextInput(QWaylandObject *container, QWaylandCompositor *compositor)
+ : QWaylandExtensionTemplate(container, *new QWaylandTextInputPrivate(compositor))
+{
+ connect(&d_func()->focusDestroyListener, &QWaylandDestroyListener::fired,
+ this, &QWaylandTextInput::focusSurfaceDestroyed);
+
+ connect(qApp->inputMethod(), &QInputMethod::visibleChanged,
+ this, &QWaylandTextInput::sendInputPanelState);
+ connect(qApp->inputMethod(), &QInputMethod::keyboardRectangleChanged,
+ this, &QWaylandTextInput::sendInputPanelState);
+ connect(qApp->inputMethod(), &QInputMethod::inputDirectionChanged,
+ this, &QWaylandTextInput::sendTextDirection);
+ connect(qApp->inputMethod(), &QInputMethod::localeChanged,
+ this, &QWaylandTextInput::sendLocale);
+}
+
+QWaylandTextInput::~QWaylandTextInput()
+{
+}
+
+void QWaylandTextInput::sendInputMethodEvent(QInputMethodEvent *event)
+{
+ Q_D(QWaylandTextInput);
+
+ d->sendInputMethodEvent(event);
+}
+
+void QWaylandTextInput::sendKeyEvent(QKeyEvent *event)
+{
+ Q_D(QWaylandTextInput);
+
+ d->sendKeyEvent(event);
+}
+
+void QWaylandTextInput::sendInputPanelState()
+{
+ Q_D(QWaylandTextInput);
+
+ d->sendInputPanelState();
+}
+
+void QWaylandTextInput::sendTextDirection()
+{
+ Q_D(QWaylandTextInput);
+
+ d->sendTextDirection();
+}
+
+void QWaylandTextInput::sendLocale()
+{
+ Q_D(QWaylandTextInput);
+
+ d->sendLocale();
+}
+
+QVariant QWaylandTextInput::inputMethodQuery(Qt::InputMethodQuery property, QVariant argument) const
+{
+ const Q_D(QWaylandTextInput);
+
+ return d->inputMethodQuery(property, argument);
+}
+
+QWaylandSurface *QWaylandTextInput::focus() const
+{
+ const Q_D(QWaylandTextInput);
+
+ return d->focus;
+}
+
+void QWaylandTextInput::setFocus(QWaylandSurface *surface)
+{
+ Q_D(QWaylandTextInput);
+
+ d->setFocus(surface);
+}
+
+void QWaylandTextInput::focusSurfaceDestroyed(void *)
+{
+ Q_D(QWaylandTextInput);
+
+ d->focusDestroyListener.reset();
+
+ d->focus = nullptr;
+ d->focusResource = nullptr;
+}
+
+bool QWaylandTextInput::isSurfaceEnabled(QWaylandSurface *surface) const
+{
+ const Q_D(QWaylandTextInput);
+
+ return d->enabledSurfaces.values().contains(surface);
+}
+
+void QWaylandTextInput::add(::wl_client *client, uint32_t id, int version)
+{
+ Q_D(QWaylandTextInput);
+
+ d->add(client, id, version);
+}
+
+const wl_interface *QWaylandTextInput::interface()
+{
+ return QWaylandTextInputPrivate::interface();
+}
+
+QByteArray QWaylandTextInput::interfaceName()
+{
+ return QWaylandTextInputPrivate::interfaceName();
+}
+
+QT_END_NAMESPACE
diff --git a/src/compositor/extensions/qwlinputpanelsurface_p.h b/src/compositor/extensions/qwaylandtextinput.h
index e11923bd0..100384e76 100644
--- a/src/compositor/extensions/qwlinputpanelsurface_p.h
+++ b/src/compositor/extensions/qwaylandtextinput.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
-** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2013-2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
@@ -35,61 +34,53 @@
**
****************************************************************************/
-#ifndef QTWAYLAND_QWLINPUTPANELSURFACE_P_H
-#define QTWAYLAND_QWLINPUTPANELSURFACE_P_H
+#ifndef QWAYLANDTEXTINPUT_H
+#define QWAYLANDTEXTINPUT_H
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtWaylandCompositor/private/qwayland-server-input-method.h>
-
-#include <QWaylandSurface>
+#include <QtWaylandCompositor/QWaylandExtension>
QT_BEGIN_NAMESPACE
-class QWaylandOutput;
+class QWaylandTextInputPrivate;
-namespace QtWayland {
+class QInputMethodEvent;
+class QKeyEvent;
+class QWaylandSurface;
-class InputPanelSurface : public QtWaylandServer::wl_input_panel_surface
+class QWaylandTextInput : public QWaylandExtensionTemplate<QWaylandTextInput>
{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWaylandTextInput)
public:
- enum Type {
- Invalid,
- Toplevel,
- OverlayPanel
- };
+ explicit QWaylandTextInput(QWaylandObject *container, QWaylandCompositor *compositor);
+ ~QWaylandTextInput();
- InputPanelSurface(struct ::wl_client *client, int id, QWaylandSurface *surface);
+ void sendInputMethodEvent(QInputMethodEvent *event);
+ void sendKeyEvent(QKeyEvent *event);
- Type type() const;
+ QVariant inputMethodQuery(Qt::InputMethodQuery property, QVariant argument) const;
- QWaylandOutput *output() const;
- wl_input_panel_surface::position position() const;
+ QWaylandSurface *focus() const;
+ void setFocus(QWaylandSurface *surface);
-protected:
- void input_panel_surface_set_overlay_panel(Resource *resource) Q_DECL_OVERRIDE;
- void input_panel_surface_set_toplevel(Resource *resource, wl_resource *output_resource, uint32_t position) Q_DECL_OVERRIDE;
+ bool isSurfaceEnabled(QWaylandSurface *surface) const;
-private:
- QWaylandSurface *m_surface;
+ void add(::wl_client *client, uint32_t id, int version);
+ static const struct wl_interface *interface();
+ static QByteArray interfaceName();
- Type m_type;
+Q_SIGNALS:
+ void updateInputMethod(Qt::InputMethodQueries queries);
+ void surfaceEnabled(QWaylandSurface *surface);
+ void surfaceDisabled(QWaylandSurface *surface);
- QWaylandOutput *m_output;
- wl_input_panel_surface::position m_position;
+private:
+ void focusSurfaceDestroyed(void *);
+ void sendInputPanelState();
+ void sendTextDirection();
+ void sendLocale();
};
-} // namespace QtWayland
-
QT_END_NAMESPACE
-#endif // QTWAYLAND_QWLINPUTPANELSURFACE_P_H
+#endif // QWAYLANDTEXTINPUT_H
diff --git a/src/compositor/extensions/qwaylandtextinput_p.h b/src/compositor/extensions/qwaylandtextinput_p.h
new file mode 100644
index 000000000..79706a7e2
--- /dev/null
+++ b/src/compositor/extensions/qwaylandtextinput_p.h
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDTEXTINPUT_P_H
+#define QWAYLANDTEXTINPUT_P_H
+
+#include <QtWaylandCompositor/private/qwaylandextension_p.h>
+#include <QtWaylandCompositor/private/qwayland-server-text-input-unstable-v2.h>
+#include <QtWaylandCompositor/QWaylandDestroyListener>
+
+#include <QtCore/QObject>
+#include <QtCore/QMap>
+#include <QtCore/QRect>
+#include <QtCore/QVector>
+#include <QtGui/QInputMethod>
+#include <QtWaylandCompositor/QWaylandSurface>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QInputMethodEvent;
+class QKeyEvent;
+class QWaylandCompositor;
+class QWaylandView;
+
+class QWaylandTextInputClientState {
+public:
+ QWaylandTextInputClientState();
+
+ Qt::InputMethodQueries updatedQueries(const QWaylandTextInputClientState &other) const;
+ Qt::InputMethodQueries mergeChanged(const QWaylandTextInputClientState &other);
+
+ Qt::InputMethodHints hints;
+ QRect cursorRectangle;
+ QString surroundingText;
+ int cursorPosition;
+ int anchorPosition;
+ QString preferredLanguage;
+
+ Qt::InputMethodQueries changedState;
+};
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandTextInputPrivate : public QWaylandExtensionTemplatePrivate, public QtWaylandServer::zwp_text_input_v2
+{
+ Q_DECLARE_PUBLIC(QWaylandTextInput)
+public:
+ explicit QWaylandTextInputPrivate(QWaylandCompositor *compositor);
+
+ void sendInputMethodEvent(QInputMethodEvent *event);
+ void sendKeyEvent(QKeyEvent *event);
+ void sendInputPanelState();
+ void sendTextDirection();
+ void sendLocale();
+
+ QVariant inputMethodQuery(Qt::InputMethodQuery property, QVariant argument) const;
+
+ void setFocus(QWaylandSurface *surface);
+
+ QWaylandCompositor *compositor;
+
+ QWaylandSurface *focus;
+ Resource *focusResource;
+ QWaylandDestroyListener focusDestroyListener;
+
+ bool inputPanelVisible;
+
+ QScopedPointer<QWaylandTextInputClientState> currentState;
+ QScopedPointer<QWaylandTextInputClientState> pendingState;
+
+ uint32_t serial;
+
+ QHash<Resource *, QWaylandSurface*> enabledSurfaces;
+
+protected:
+ void zwp_text_input_v2_bind_resource(Resource *resource) Q_DECL_OVERRIDE;
+ void zwp_text_input_v2_destroy_resource(Resource *resource) Q_DECL_OVERRIDE;
+
+ void zwp_text_input_v2_destroy(Resource *resource) Q_DECL_OVERRIDE;
+ void zwp_text_input_v2_enable(Resource *resource, wl_resource *surface) Q_DECL_OVERRIDE;
+ void zwp_text_input_v2_disable(Resource *resource, wl_resource *surface) Q_DECL_OVERRIDE;
+ void zwp_text_input_v2_show_input_panel(Resource *resource) Q_DECL_OVERRIDE;
+ void zwp_text_input_v2_hide_input_panel(Resource *resource) Q_DECL_OVERRIDE;
+ void zwp_text_input_v2_set_surrounding_text(Resource *resource, const QString &text, int32_t cursor, int32_t anchor) Q_DECL_OVERRIDE;
+ void zwp_text_input_v2_set_content_type(Resource *resource, uint32_t hint, uint32_t purpose) Q_DECL_OVERRIDE;
+ void zwp_text_input_v2_set_cursor_rectangle(Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) Q_DECL_OVERRIDE;
+ void zwp_text_input_v2_set_preferred_language(Resource *resource, const QString &language) Q_DECL_OVERRIDE;
+ void zwp_text_input_v2_update_state(Resource *resource, uint32_t serial, uint32_t flags) Q_DECL_OVERRIDE;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDTEXTINPUT_P_H
diff --git a/src/compositor/extensions/qwaylandtextinputmanager.cpp b/src/compositor/extensions/qwaylandtextinputmanager.cpp
new file mode 100644
index 000000000..62e8ac88c
--- /dev/null
+++ b/src/compositor/extensions/qwaylandtextinputmanager.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandtextinputmanager.h"
+#include "qwaylandtextinputmanager_p.h"
+
+#include <QtWaylandCompositor/QWaylandCompositor>
+#include <QtWaylandCompositor/QWaylandInputDevice>
+
+#include "qwaylandtextinput.h"
+
+QT_BEGIN_NAMESPACE
+
+QWaylandTextInputManagerPrivate::QWaylandTextInputManagerPrivate()
+ : QWaylandExtensionTemplatePrivate()
+ , QtWaylandServer::zwp_text_input_manager_v2()
+{
+}
+
+void QWaylandTextInputManagerPrivate::zwp_text_input_manager_v2_get_text_input(Resource *resource, uint32_t id, struct ::wl_resource *seat)
+{
+ Q_Q(QWaylandTextInputManager);
+ QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(q->extensionContainer());
+ QWaylandInputDevice *inputDevice = QWaylandInputDevice::fromSeatResource(seat);
+ QWaylandTextInput *textInput = QWaylandTextInput::findIn(inputDevice);
+ if (!textInput) {
+ textInput = new QWaylandTextInput(inputDevice, compositor);
+ }
+ textInput->add(resource->client(), id, wl_resource_get_version(resource->handle));
+}
+
+QWaylandTextInputManager::QWaylandTextInputManager()
+ : QWaylandExtensionTemplate<QWaylandTextInputManager>(*new QWaylandTextInputManagerPrivate)
+{
+}
+
+QWaylandTextInputManager::QWaylandTextInputManager(QWaylandCompositor *compositor)
+ : QWaylandExtensionTemplate<QWaylandTextInputManager>(compositor, *new QWaylandTextInputManagerPrivate)
+{
+}
+
+void QWaylandTextInputManager::initialize()
+{
+ Q_D(QWaylandTextInputManager);
+
+ QWaylandExtensionTemplate::initialize();
+ QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer());
+ if (!compositor) {
+ qWarning() << "Failed to find QWaylandCompositor when initializing QWaylandTextInputManager";
+ return;
+ }
+ d->init(compositor->display(), 1);
+}
+
+const wl_interface *QWaylandTextInputManager::interface()
+{
+ return QWaylandTextInputManagerPrivate::interface();
+}
+
+QByteArray QWaylandTextInputManager::interfaceName()
+{
+ return QWaylandTextInputManagerPrivate::interfaceName();
+}
+
+QT_END_NAMESPACE
diff --git a/src/compositor/extensions/qwltextinputmanager.cpp b/src/compositor/extensions/qwaylandtextinputmanager.h
index 9c7dd72f4..6c250d58c 100644
--- a/src/compositor/extensions/qwltextinputmanager.cpp
+++ b/src/compositor/extensions/qwaylandtextinputmanager.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
@@ -34,31 +34,31 @@
**
****************************************************************************/
-#include "qwltextinputmanager_p.h"
+#ifndef QWAYLANDTEXTINPUTMANAGER_H
+#define QWAYLANDTEXTINPUTMANAGER_H
-#include <QtWaylandCompositor/QWaylandCompositor>
-#include "qwltextinput_p.h"
+#include <QtWaylandCompositor/QWaylandExtension>
+
+#include <QtCore/QSize>
QT_BEGIN_NAMESPACE
-namespace QtWayland {
+class QWaylandTextInputManagerPrivate;
-TextInputManager::TextInputManager(QWaylandCompositor *compositor)
- : QWaylandExtensionTemplate(compositor)
- , QtWaylandServer::wl_text_input_manager(compositor->display(), 1)
- , m_compositor(compositor)
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandTextInputManager : public QWaylandExtensionTemplate<QWaylandTextInputManager>
{
-}
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWaylandTextInputManager)
+public:
+ QWaylandTextInputManager();
+ QWaylandTextInputManager(QWaylandCompositor *compositor);
-TextInputManager::~TextInputManager()
-{
-}
+ void initialize() Q_DECL_OVERRIDE;
-void TextInputManager::text_input_manager_create_text_input(Resource *resource, uint32_t id)
-{
- new TextInput(this, m_compositor, resource->client(), id);
-}
-
-} // namespace QtWayland
+ static const struct wl_interface *interface();
+ static QByteArray interfaceName();
+};
QT_END_NAMESPACE
+
+#endif // QWAYLANDTEXTINPUTMANAGER_H
diff --git a/src/compositor/extensions/qwltextinputmanager_p.h b/src/compositor/extensions/qwaylandtextinputmanager_p.h
index 0125bdcae..8052301c9 100644
--- a/src/compositor/extensions/qwltextinputmanager_p.h
+++ b/src/compositor/extensions/qwaylandtextinputmanager_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2013-2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
@@ -34,11 +34,12 @@
**
****************************************************************************/
-#ifndef QTWAYLAND_QWLTEXTINPUTMANAGER_P_H
-#define QTWAYLAND_QWLTEXTINPUTMANAGER_P_H
+#ifndef QWAYLANDTEXTINPUTMANAGER_P_H
+#define QWAYLANDTEXTINPUTMANAGER_P_H
-#include <QtWaylandCompositor/QWaylandExtension>
-#include <QtWaylandCompositor/private/qwayland-server-text.h>
+#include <QtWaylandCompositor/private/qwaylandextension_p.h>
+
+#include <QtWaylandCompositor/private/qwayland-server-text-input-unstable-v2.h>
//
// W A R N I N G
@@ -53,26 +54,16 @@
QT_BEGIN_NAMESPACE
-class QWaylandCompositor;
-
-namespace QtWayland {
-
-class TextInputManager : public QWaylandExtensionTemplate<TextInputManager>, public QtWaylandServer::wl_text_input_manager
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandTextInputManagerPrivate : public QWaylandExtensionTemplatePrivate, public QtWaylandServer::zwp_text_input_manager_v2
{
- Q_OBJECT
+ Q_DECLARE_PUBLIC(QWaylandTextInputManager)
public:
- TextInputManager(QWaylandCompositor *compositor);
- ~TextInputManager();
+ QWaylandTextInputManagerPrivate();
protected:
- void text_input_manager_create_text_input(Resource *resource, uint32_t id) Q_DECL_OVERRIDE;
-
-private:
- QWaylandCompositor *m_compositor;
+ void zwp_text_input_manager_v2_get_text_input(Resource *resource, uint32_t id, struct ::wl_resource *seat) Q_DECL_OVERRIDE;
};
-} // namespace QtWayland
-
QT_END_NAMESPACE
-#endif // QTWAYLAND_QWLTEXTINPUTMANAGER_P_H
+#endif // QWAYLANDTEXTINPUTMANAGER_P_H
diff --git a/src/compositor/extensions/qwlinputmethod.cpp b/src/compositor/extensions/qwlinputmethod.cpp
deleted file mode 100644
index 6cf23bcb1..000000000
--- a/src/compositor/extensions/qwlinputmethod.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qwlinputmethod_p.h"
-
-#include <QtWaylandCompositor/QWaylandCompositor>
-#include <QtWaylandCompositor/QWaylandKeyboard>
-#include <QtWaylandCompositor/QWaylandInputDevice>
-#include "qwlinputmethodcontext_p.h"
-#include "qwlinputpanel_p.h"
-#include "qwltextinput_p.h"
-
-QT_BEGIN_NAMESPACE
-
-namespace QtWayland {
-
-InputMethod::InputMethod(QWaylandInputDevice *seat)
- : QWaylandExtensionTemplate<InputMethod>(seat)
- , QtWaylandServer::wl_input_method(seat->compositor()->display(), 1)
- , m_seat(seat)
- , m_resource(0)
- , m_textInput()
- , m_context()
-{
- connect(seat->keyboard(), &QWaylandKeyboard::focusChanged, this, &InputMethod::focusChanged);
-}
-
-InputMethod::~InputMethod()
-{
-}
-
-void InputMethod::activate(TextInput *textInput)
-{
- if (!m_resource) {
- qDebug("Cannot activate (no input method running).");
- return;
- }
-
- if (m_textInput) {
- Q_ASSERT(m_textInput != textInput);
- m_textInput->deactivate(this);
- }
- m_textInput = textInput;
- m_context = new InputMethodContext(m_resource->client(), textInput);
-
- send_activate(m_resource->handle, m_context->resource()->handle);
-
- QWaylandInputPanelPrivate *panel = QWaylandInputPanelPrivate::findIn(compositor());
- if (panel) {
- panel->setFocus(textInput->focus());
- panel->setCursorRectangle(textInput->cursorRectangle());
- panel->setInputPanelVisible(textInput->inputPanelVisible());
- }
-}
-
-void InputMethod::deactivate()
-{
- if (!m_resource) {
- qDebug("Cannot deactivate (no input method running).");
- return;
- }
-
- send_deactivate(m_resource->handle, m_context->resource()->handle);
- m_textInput = 0;
- m_context = 0;
-
- QWaylandInputPanelPrivate *panel = QWaylandInputPanelPrivate::findIn(compositor());
- if (panel) {
- panel->setFocus(0);
- panel->setCursorRectangle(QRect());
- panel->setInputPanelVisible(false);
- }
-}
-
-void InputMethod::focusChanged(QWaylandSurface *surface)
-{
- if (!m_textInput)
- return;
-
- if (!surface || m_textInput->focus() != surface) {
- m_textInput->deactivate(this);
- }
-}
-
-bool InputMethod::isBound() const
-{
- return m_resource != 0;
-}
-
-InputMethodContext *InputMethod::context() const
-{
- return m_context;
-}
-
-TextInput *InputMethod::textInput() const
-{
- return m_textInput;
-}
-
-void InputMethod::input_method_bind_resource(Resource *resource)
-{
- if (m_resource) {
- wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "interface object already bound");
- wl_resource_destroy(resource->handle);
- return;
- }
-
- m_resource = resource;
-}
-
-void InputMethod::input_method_destroy_resource(Resource *resource)
-{
- Q_ASSERT(resource == m_resource);
- m_resource = 0;
-}
-
-} // namespace QtWayland
-
-QT_END_NAMESPACE
diff --git a/src/compositor/extensions/qwlinputmethod_p.h b/src/compositor/extensions/qwlinputmethod_p.h
deleted file mode 100644
index 69348df6c..000000000
--- a/src/compositor/extensions/qwlinputmethod_p.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QTWAYLAND_QWLINPUTMETHOD_H
-#define QTWAYLAND_QWLINPUTMETHOD_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtWaylandCompositor/private/qwayland-server-input-method.h>
-#include <QtWaylandCompositor/QWaylandExtension>
-#include <QtWaylandCompositor/QWaylandInputDevice>
-
-#include <QObject>
-#include <QScopedPointer>
-
-#include <QtWaylandCompositor/QWaylandSurface>
-
-QT_BEGIN_NAMESPACE
-
-class QWaylandInputDevice;
-class QWaylandCompositor;
-
-namespace QtWayland {
-
-class InputMethodContext;
-class TextInput;
-
-class InputMethod : public QWaylandExtensionTemplate<InputMethod> , public QtWaylandServer::wl_input_method
-{
- Q_OBJECT
-public:
- explicit InputMethod(QWaylandInputDevice *seat);
- ~InputMethod();
-
- QWaylandCompositor *compositor() const { return m_seat->compositor(); }
-
- void activate(TextInput *textInput);
- void deactivate();
-
- bool isBound() const;
-
- InputMethodContext *context() const;
- TextInput *textInput() const;
-
-protected:
- void input_method_bind_resource(Resource *resource);
- void input_method_destroy_resource(Resource *resource);
-
-private Q_SLOTS:
- void focusChanged(QWaylandSurface *surface);
-
-private:
- QWaylandInputDevice *m_seat;
- Resource *m_resource;
- TextInput *m_textInput;
- InputMethodContext *m_context;
-};
-
-} // namespace QtWayland
-
-QT_END_NAMESPACE
-
-#endif // QTWAYLAND_QWLINPUTMETHOD_H
diff --git a/src/compositor/extensions/qwlinputmethodcontext.cpp b/src/compositor/extensions/qwlinputmethodcontext.cpp
deleted file mode 100644
index 6421d5e76..000000000
--- a/src/compositor/extensions/qwlinputmethodcontext.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qwlinputmethodcontext_p.h"
-
-#include "qwltextinput_p.h"
-
-QT_BEGIN_NAMESPACE
-
-namespace QtWayland {
-
-InputMethodContext::InputMethodContext(wl_client *client, TextInput *textInput)
- : QtWaylandServer::wl_input_method_context(client, 0, 1)
- , m_textInput(textInput)
-{
-}
-
-InputMethodContext::~InputMethodContext()
-{
-}
-
-void InputMethodContext::input_method_context_destroy_resource(Resource *)
-{
- delete this;
-}
-
-void InputMethodContext::input_method_context_destroy(Resource *resource)
-{
- wl_resource_destroy(resource->handle);
-}
-
-void InputMethodContext::input_method_context_commit_string(Resource *, uint32_t serial, const QString &text)
-{
- m_textInput->send_commit_string(serial, text);
-}
-
-void InputMethodContext::input_method_context_cursor_position(Resource *, int32_t index, int32_t anchor)
-{
- m_textInput->send_cursor_position(index, anchor);
-}
-
-void InputMethodContext::input_method_context_delete_surrounding_text(Resource *, int32_t index, uint32_t length)
-{
- m_textInput->send_delete_surrounding_text(index, length);
-}
-
-void InputMethodContext::input_method_context_language(Resource *, uint32_t serial, const QString &language)
-{
- m_textInput->send_language(serial, language);
-}
-
-void InputMethodContext::input_method_context_keysym(Resource *, uint32_t serial, uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers)
-{
- m_textInput->send_keysym(serial, time, sym, state, modifiers);
-}
-
-void InputMethodContext::input_method_context_modifiers_map(Resource *, wl_array *map)
-{
- QByteArray modifiersArray(static_cast<char *>(map->data), map->size);
- m_textInput->send_modifiers_map(modifiersArray);
-}
-
-void InputMethodContext::input_method_context_preedit_cursor(Resource *, int32_t index)
-{
- m_textInput->send_preedit_cursor(index);
-}
-
-void InputMethodContext::input_method_context_preedit_string(Resource *, uint32_t serial, const QString &text, const QString &commit)
-{
- m_textInput->send_preedit_string(serial, text, commit);
-}
-
-void InputMethodContext::input_method_context_preedit_styling(Resource *, uint32_t index, uint32_t length, uint32_t style)
-{
- m_textInput->send_preedit_styling(index, length, style);
-}
-
-void InputMethodContext::input_method_context_grab_keyboard(Resource *, uint32_t keyboard)
-{
- Q_UNUSED(keyboard);
-}
-
-void InputMethodContext::input_method_context_key(Resource *, uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
-{
- Q_UNUSED(serial);
- Q_UNUSED(time);
- Q_UNUSED(key);
- Q_UNUSED(state);
-}
-
-void InputMethodContext::input_method_context_modifiers(Resource *, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
-{
- Q_UNUSED(serial);
- Q_UNUSED(mods_depressed);
- Q_UNUSED(mods_latched);
- Q_UNUSED(mods_locked);
- Q_UNUSED(group);
-}
-
-} // namespace QtWayland
-
-QT_END_NAMESPACE
diff --git a/src/compositor/extensions/qwlinputmethodcontext_p.h b/src/compositor/extensions/qwlinputmethodcontext_p.h
deleted file mode 100644
index febadc957..000000000
--- a/src/compositor/extensions/qwlinputmethodcontext_p.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QTWAYLAND_QWLINPUTMETHODCONTEXT_P_H
-#define QTWAYLAND_QWLINPUTMETHODCONTEXT_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtWaylandCompositor/private/qwayland-server-input-method.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace QtWayland {
-
-class TextInput;
-
-class InputMethodContext : public QtWaylandServer::wl_input_method_context
-{
-public:
- explicit InputMethodContext(struct ::wl_client *client, TextInput *textInput);
- ~InputMethodContext();
-
-protected:
- void input_method_context_destroy_resource(Resource *resource) Q_DECL_OVERRIDE;
- void input_method_context_destroy(Resource *resource) Q_DECL_OVERRIDE;
-
- void input_method_context_commit_string(Resource *resource, uint32_t serial, const QString &text) Q_DECL_OVERRIDE;
- void input_method_context_cursor_position(Resource *resource, int32_t index, int32_t anchor) Q_DECL_OVERRIDE;
- void input_method_context_delete_surrounding_text(Resource *resource, int32_t index, uint32_t length) Q_DECL_OVERRIDE;
- void input_method_context_language(Resource *resource, uint32_t serial, const QString &language) Q_DECL_OVERRIDE;
- void input_method_context_keysym(Resource *resource, uint32_t serial, uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers) Q_DECL_OVERRIDE;
- void input_method_context_modifiers_map(Resource *resource, wl_array *map) Q_DECL_OVERRIDE;
- void input_method_context_preedit_cursor(Resource *resource, int32_t index) Q_DECL_OVERRIDE;
- void input_method_context_preedit_string(Resource *resource, uint32_t serial, const QString &text, const QString &commit) Q_DECL_OVERRIDE;
- void input_method_context_preedit_styling(Resource *resource, uint32_t index, uint32_t length, uint32_t style) Q_DECL_OVERRIDE;
- void input_method_context_grab_keyboard(Resource *resource, uint32_t keyboard) Q_DECL_OVERRIDE;
- void input_method_context_key(Resource *resource, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) Q_DECL_OVERRIDE;
- void input_method_context_modifiers(Resource *resource, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) Q_DECL_OVERRIDE;
-
-private:
- TextInput *m_textInput;
-};
-
-} // namespace QtWayland
-
-QT_END_NAMESPACE
-
-#endif // QTWAYLAND_QWLINPUTMETHODCONTEXT_P_H
diff --git a/src/compositor/extensions/qwlinputpanel.cpp b/src/compositor/extensions/qwlinputpanel.cpp
deleted file mode 100644
index 8f41f0ca3..000000000
--- a/src/compositor/extensions/qwlinputpanel.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qwlinputpanel_p.h"
-
-#include <QtWaylandCompositor/qwaylandinputpanel.h>
-#include <QtWaylandCompositor/QWaylandCompositor>
-
-#include "qwlinputmethod_p.h"
-#include "qwlinputpanelsurface_p.h"
-#include "qwltextinput_p.h"
-
-QT_BEGIN_NAMESPACE
-
-QWaylandInputPanelPrivate::QWaylandInputPanelPrivate(QWaylandCompositor *compositor)
- : QWaylandExtensionTemplatePrivate()
- , QtWaylandServer::wl_input_panel()
- , m_compositor(compositor)
- , m_focus()
- , m_inputPanelVisible(false)
- , m_cursorRectangle()
-{
- init(compositor->display(), 1);
-}
-
-QWaylandInputPanelPrivate::~QWaylandInputPanelPrivate()
-{
-}
-
-QWaylandInputPanel *QWaylandInputPanelPrivate::waylandInputPanel() const
-{
- QWaylandInputPanel *panel = const_cast<QWaylandInputPanel *>(q_func());
- return panel;
-}
-
-QWaylandSurface *QWaylandInputPanelPrivate::focus() const
-{
- return m_focus;
-}
-
-void QWaylandInputPanelPrivate::setFocus(QWaylandSurface *focus)
-{
- Q_Q(QWaylandInputPanel);
- if (m_focus == focus)
- return;
-
- m_focus = focus;
-
- Q_EMIT q->focusChanged();
-}
-
-bool QWaylandInputPanelPrivate::inputPanelVisible() const
-{
- return m_inputPanelVisible;
-}
-
-void QWaylandInputPanelPrivate::setInputPanelVisible(bool inputPanelVisible)
-{
- Q_Q(QWaylandInputPanel);
- if (m_inputPanelVisible == inputPanelVisible)
- return;
-
- m_inputPanelVisible = inputPanelVisible;
-
- q->visibleChanged();
-}
-
-QRect QWaylandInputPanelPrivate::cursorRectangle() const
-{
- return m_cursorRectangle;
-}
-
-void QWaylandInputPanelPrivate::setCursorRectangle(const QRect &cursorRectangle)
-{
- Q_Q(QWaylandInputPanel);
- if (m_cursorRectangle == cursorRectangle)
- return;
-
- m_cursorRectangle = cursorRectangle;
-
- Q_EMIT q->cursorRectangleChanged();
-}
-
-QWaylandInputPanelPrivate *QWaylandInputPanelPrivate::findIn(QWaylandObject *container)
-{
- QWaylandInputPanel *panel = QWaylandInputPanel::findIn(container);
- if (!panel)
- return Q_NULLPTR;
- return panel->d_func();
-}
-
-void QWaylandInputPanelPrivate::input_panel_get_input_panel_surface(Resource *resource, uint32_t id, wl_resource *surface)
-{
- new QtWayland::InputPanelSurface(resource->client(), id, QWaylandSurface::fromResource(surface));
-}
-
-QT_END_NAMESPACE
diff --git a/src/compositor/extensions/qwlinputpanel_p.h b/src/compositor/extensions/qwlinputpanel_p.h
deleted file mode 100644
index 97720f050..000000000
--- a/src/compositor/extensions/qwlinputpanel_p.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QTWAYLAND_QWLINPUTPANEL_P_H
-#define QTWAYLAND_QWLINPUTPANEL_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtWaylandCompositor/qwaylandexport.h>
-#include <QtWaylandCompositor/qwaylandinputpanel.h>
-
-#include <QtWaylandCompositor/private/qwaylandextension_p.h>
-#include <QtWaylandCompositor/private/qwayland-server-input-method.h>
-
-#include <QRect>
-#include <QScopedPointer>
-
-QT_BEGIN_NAMESPACE
-
-namespace QtWayland {
-class TextInput;
-}
-
-
-class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandInputPanelPrivate : public QWaylandExtensionTemplatePrivate, public QtWaylandServer::wl_input_panel
-{
- Q_DECLARE_PUBLIC(QWaylandInputPanel)
-public:
- QWaylandInputPanelPrivate(QWaylandCompositor *compositor);
- ~QWaylandInputPanelPrivate();
-
- QWaylandInputPanel *waylandInputPanel() const;
-
- QWaylandSurface *focus() const;
- void setFocus(QWaylandSurface *focus);
-
- bool inputPanelVisible() const;
- void setInputPanelVisible(bool inputPanelVisible);
-
- QRect cursorRectangle() const;
- void setCursorRectangle(const QRect &cursorRectangle);
-
- static QWaylandInputPanelPrivate *findIn(QWaylandObject *container);
-protected:
- void input_panel_get_input_panel_surface(Resource *resource, uint32_t id, struct ::wl_resource *surface) Q_DECL_OVERRIDE;
-
-private:
- QWaylandCompositor *m_compositor;
-
- QWaylandSurface *m_focus;
- bool m_inputPanelVisible;
- QRect m_cursorRectangle;
-};
-
-QT_END_NAMESPACE
-
-#endif // QTWAYLAND_QWLINPUTPANEL_P_H
diff --git a/src/compositor/extensions/qwlinputpanelsurface.cpp b/src/compositor/extensions/qwlinputpanelsurface.cpp
deleted file mode 100644
index c54520aad..000000000
--- a/src/compositor/extensions/qwlinputpanelsurface.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
-** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qwlinputpanelsurface_p.h"
-
-#include <QtWaylandCompositor/private/qwaylandsurface_p.h>
-#include <QtWaylandCompositor/QWaylandOutput>
-
-QT_BEGIN_NAMESPACE
-
-namespace QtWayland {
-
-InputPanelSurface::InputPanelSurface(wl_client *client, int id, QWaylandSurface *surface)
- : QtWaylandServer::wl_input_panel_surface(client, id, 1)
- , m_surface(surface)
- , m_type(Invalid)
- , m_output(0)
- , m_position()
-{
- QWaylandSurfacePrivate::get(surface)->setInputPanelSurface(this);
-}
-
-InputPanelSurface::Type InputPanelSurface::type() const
-{
- return m_type;
-}
-
-QWaylandOutput *InputPanelSurface::output() const
-{
- return m_output;
-}
-
-QtWaylandServer::wl_input_panel_surface::position InputPanelSurface::position() const
-{
- return m_position;
-}
-
-void InputPanelSurface::input_panel_surface_set_overlay_panel(Resource *)
-{
- m_type = OverlayPanel;
-}
-
-void InputPanelSurface::input_panel_surface_set_toplevel(Resource *, wl_resource *output_resource, uint32_t position)
-{
- m_type = Toplevel;
- m_output = QWaylandOutput::fromResource(output_resource);
- m_position = static_cast<wl_input_panel_surface::position>(position);
-}
-
-QT_END_NAMESPACE
-
-} // namespace QtWayland
diff --git a/src/compositor/extensions/qwltextinput.cpp b/src/compositor/extensions/qwltextinput.cpp
deleted file mode 100644
index 7546ab6a0..000000000
--- a/src/compositor/extensions/qwltextinput.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qwltextinput_p.h"
-
-#include "qwlinputmethod_p.h"
-#include "qwlinputmethodcontext_p.h"
-#include "qwlinputpanel_p.h"
-#include <QtWaylandCompositor/QWaylandInputPanel>
-#include <QtWaylandCompositor/QWaylandCompositor>
-#include <QtWaylandCompositor/private/qwaylandinput_p.h>
-
-#include <algorithm>
-
-QT_BEGIN_NAMESPACE
-
-namespace QtWayland {
-
-TextInput::TextInput(QWaylandObject *container, QWaylandCompositor *compositor, struct ::wl_client *client, int id)
- : QWaylandExtensionTemplate(container)
- , wl_text_input(client, id, 1)
- , m_compositor(compositor)
- , m_focus()
- , m_inputPanelVisible()
- , m_cursorRectangle()
-{
-}
-
-QWaylandSurface *TextInput::focus() const
-{
- return m_focus;
-}
-
-bool TextInput::inputPanelVisible() const
-{
- return m_inputPanelVisible;
-}
-
-QRect TextInput::cursorRectangle() const
-{
- return m_cursorRectangle;
-}
-
-void TextInput::deactivate(InputMethod *inputMethod)
-{
- if (m_activeInputMethods.removeOne(inputMethod))
- inputMethod->deactivate();
-
- if (m_activeInputMethods.isEmpty())
- send_leave();
-}
-
-void TextInput::text_input_destroy_resource(Resource *)
-{
- Q_FOREACH (InputMethod *inputMethod, m_activeInputMethods) {
- deactivate(inputMethod);
- }
-
- delete this;
-}
-
-void TextInput::text_input_activate(Resource *, wl_resource *seat, wl_resource *surface)
-{
- QWaylandSurface *oldSurface = m_focus;
- m_focus = QWaylandSurface::fromResource(surface);
-
- if (oldSurface != m_focus)
- send_leave();
-
- bool wasEmpty = m_activeInputMethods.isEmpty();
-
- InputMethod *inputMethod = InputMethod::findIn(QWaylandInputDevice::fromSeatResource(seat));
-
- if (inputMethod && !m_activeInputMethods.contains(inputMethod)) {
- m_activeInputMethods.append(inputMethod);
- inputMethod->activate(this);
- }
-
- if (wasEmpty || oldSurface != m_focus)
- send_enter(surface);
-}
-
-void TextInput::text_input_deactivate(Resource *, wl_resource *seat)
-{
- InputMethod *inputMethod = InputMethod::findIn(QWaylandInputDevice::fromSeatResource(seat));
-
- if (inputMethod)
- deactivate(inputMethod);
-}
-
-static bool isInputMethodBound(InputMethod *inputMethod)
-{
- return inputMethod->isBound();
-}
-
-void TextInput::text_input_show_input_panel(Resource *)
-{
- m_inputPanelVisible = true;
-
- if (std::find_if(m_activeInputMethods.cbegin(), m_activeInputMethods.cend(), isInputMethodBound) != m_activeInputMethods.cend()){
- QWaylandInputPanelPrivate *panel = QWaylandInputPanelPrivate::findIn(m_compositor);
- if (panel)
- panel->setInputPanelVisible(true);
- }
-}
-
-void TextInput::text_input_hide_input_panel(Resource *)
-{
- m_inputPanelVisible = false;
-
- if (std::find_if(m_activeInputMethods.cbegin(), m_activeInputMethods.cend(), isInputMethodBound) != m_activeInputMethods.cend()) {
- QWaylandInputPanelPrivate *panel = QWaylandInputPanelPrivate::findIn(m_compositor);
- if (panel)
- panel->setInputPanelVisible(false);
- }
-}
-
-void TextInput::text_input_set_cursor_rectangle(Resource *, int32_t x, int32_t y, int32_t width, int32_t height)
-{
- m_cursorRectangle = QRect(x, y, width, height);
-
- if (!m_activeInputMethods.isEmpty()) {
- QWaylandInputPanelPrivate *panel = QWaylandInputPanelPrivate::findIn(m_compositor);
- if (panel)
- panel->setCursorRectangle(m_cursorRectangle);
- }
-}
-
-void TextInput::text_input_reset(Resource *)
-{
- Q_FOREACH (InputMethod *inputMethod, m_activeInputMethods) {
- if (inputMethod->context())
- inputMethod->context()->send_reset();
- }
-}
-
-void TextInput::text_input_commit_state(Resource *, uint32_t serial)
-{
- Q_FOREACH (InputMethod *inputMethod, m_activeInputMethods) {
- if (inputMethod->context())
- inputMethod->context()->send_commit_state(serial);
- }
-}
-
-void TextInput::text_input_set_content_type(Resource *, uint32_t hint, uint32_t purpose)
-{
- Q_FOREACH (InputMethod *inputMethod, m_activeInputMethods) {
- if (inputMethod->context())
- inputMethod->context()->send_content_type(hint, purpose);
- }
-}
-
-void TextInput::text_input_set_preferred_language(Resource *, const QString &language)
-{
- Q_FOREACH (InputMethod *inputMethod, m_activeInputMethods) {
- if (inputMethod->context())
- inputMethod->context()->send_preferred_language(language);
- }
-}
-
-void TextInput::text_input_set_surrounding_text(Resource *, const QString &text, uint32_t cursor, uint32_t anchor)
-{
- Q_FOREACH (InputMethod *inputMethod, m_activeInputMethods) {
- if (inputMethod->context())
- inputMethod->context()->send_surrounding_text(text, cursor, anchor);
- }
-}
-
-void TextInput::text_input_invoke_action(Resource *, uint32_t button, uint32_t index)
-{
- Q_FOREACH (InputMethod *inputMethod, m_activeInputMethods) {
- if (inputMethod->context())
- inputMethod->context()->send_invoke_action(button, index);
- }
-}
-
-} // namespace QtWayland
-
-QT_END_NAMESPACE
diff --git a/src/compositor/extensions/qwltextinput_p.h b/src/compositor/extensions/qwltextinput_p.h
deleted file mode 100644
index 02adc5cae..000000000
--- a/src/compositor/extensions/qwltextinput_p.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QTWAYLAND_QWLTEXTINPUT_P_H
-#define QTWAYLAND_QWLTEXTINPUT_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtWaylandCompositor/QWaylandExtension>
-#include <QtWaylandCompositor/private/qwayland-server-text.h>
-
-#include <QRect>
-
-QT_BEGIN_NAMESPACE
-
-class QWaylandSurface;
-class QWaylandCompositor;
-
-namespace QtWayland {
-
-class InputMethod;
-
-class TextInput : public QWaylandExtensionTemplate<TextInput>, public QtWaylandServer::wl_text_input
-{
-public:
- explicit TextInput(QWaylandObject *container, QWaylandCompositor *compositor, struct ::wl_client *client, int id);
-
- QWaylandSurface *focus() const;
-
- bool inputPanelVisible() const;
- QRect cursorRectangle() const;
-
- void deactivate(InputMethod *inputMethod);
-
-protected:
- void text_input_destroy_resource(Resource *resource) Q_DECL_OVERRIDE;
-
- void text_input_activate(Resource *resource, wl_resource *seat, wl_resource *surface) Q_DECL_OVERRIDE;
- void text_input_deactivate(Resource *resource, wl_resource *seat) Q_DECL_OVERRIDE;
- void text_input_show_input_panel(Resource *resource) Q_DECL_OVERRIDE;
- void text_input_hide_input_panel(Resource *resource) Q_DECL_OVERRIDE;
- void text_input_reset(Resource *resource) Q_DECL_OVERRIDE;
- void text_input_commit_state(Resource *resource, uint32_t serial) Q_DECL_OVERRIDE;
- void text_input_set_content_type(Resource *resource, uint32_t hint, uint32_t purpose) Q_DECL_OVERRIDE;
- void text_input_set_cursor_rectangle(Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) Q_DECL_OVERRIDE;
- void text_input_set_preferred_language(Resource *resource, const QString &language) Q_DECL_OVERRIDE;
- void text_input_set_surrounding_text(Resource *resource, const QString &text, uint32_t cursor, uint32_t anchor) Q_DECL_OVERRIDE;
- void text_input_invoke_action(Resource *resource, uint32_t button, uint32_t index) Q_DECL_OVERRIDE;
-
-private:
- QWaylandCompositor *m_compositor;
- QList<InputMethod*> m_activeInputMethods;
- QWaylandSurface *m_focus;
-
- bool m_inputPanelVisible;
- QRect m_cursorRectangle;
-
-};
-
-} // namespace QtWayland
-
-QT_END_NAMESPACE
-
-#endif // QTWAYLAND_QWLTEXTINPUT_P_H
diff --git a/src/imports/compositor/qwaylandquickcompositorplugin.cpp b/src/imports/compositor/qwaylandquickcompositorplugin.cpp
index 7be257d37..1fa28123d 100644
--- a/src/imports/compositor/qwaylandquickcompositorplugin.cpp
+++ b/src/imports/compositor/qwaylandquickcompositorplugin.cpp
@@ -51,6 +51,7 @@
#include <QtWaylandCompositor/QWaylandResource>
#include <QtWaylandCompositor/QWaylandWlShell>
+#include <QtWaylandCompositor/QWaylandTextInputManager>
#include <QtWaylandCompositor/qwaylandexport.h>
#include "qwaylandmousetracker_p.h"
@@ -61,6 +62,8 @@ Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandQuickCompositor)
Q_COMPOSITOR_DECLARE_QUICK_DATA_CLASS(QWaylandWlShell)
Q_COMPOSITOR_DECLARE_QUICK_DATA_CLASS(QWaylandWlShellSurface)
+Q_COMPOSITOR_DECLARE_QUICK_DATA_CLASS(QWaylandTextInputManager)
+
class QmlUrlResolver
{
public:
@@ -142,7 +145,7 @@ public:
qmlRegisterType<QWaylandWlShellQuickData>(uri, 1, 0, "WlShell");
qmlRegisterType<QWaylandWlShellSurfaceQuickData>(uri, 1, 0, "WlShellSurface");
qmlRegisterType<QWaylandQuickWlShellSurfaceItem>(uri, 1, 0, "WlShellSurfaceItem");
-
+ qmlRegisterType<QWaylandTextInputManagerQuickData>(uri, 1, 0, "TextInputManager");
}
};
//![class decl]
diff --git a/src/shared/qwaylandinputmethodeventbuilder.cpp b/src/shared/qwaylandinputmethodeventbuilder.cpp
new file mode 100644
index 000000000..eb527c15a
--- /dev/null
+++ b/src/shared/qwaylandinputmethodeventbuilder.cpp
@@ -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
+
diff --git a/src/shared/qwaylandinputmethodeventbuilder.h b/src/shared/qwaylandinputmethodeventbuilder.h
new file mode 100644
index 000000000..188a6a94b
--- /dev/null
+++ b/src/shared/qwaylandinputmethodeventbuilder.h
@@ -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
diff --git a/src/shared/qwaylandxkb.cpp b/src/shared/qwaylandxkb.cpp
index f5d0527de..32d24bd62 100644
--- a/src/shared/qwaylandxkb.cpp
+++ b/src/shared/qwaylandxkb.cpp
@@ -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
diff --git a/src/shared/qwaylandxkb.h b/src/shared/qwaylandxkb.h
index bfb38515f..9b5c935a5 100644
--- a/src/shared/qwaylandxkb.h
+++ b/src/shared/qwaylandxkb.h
@@ -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