IME support
Dialogs still need to be adapted to this. Only works for documents as of now. Change-Id: I0fb1114e279a9e563943f3f65dd5a577523e9841
This commit is contained in:
parent
1fabfd9fe3
commit
ad1da235d3
9 changed files with 102 additions and 11 deletions
|
@ -300,6 +300,11 @@ struct _LibreOfficeKitDocumentClass
|
|||
/// @see lok::Document::setViewLanguage().
|
||||
void (*setViewLanguage) (LibreOfficeKitDocument* pThis, int nId, const char* language);
|
||||
|
||||
/// @see lok::Document::postExtTextInputEvent
|
||||
void (*postExtTextInputEvent) (LibreOfficeKitDocument* pThis,
|
||||
int nType,
|
||||
const char* pText);
|
||||
|
||||
#endif // defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY
|
||||
};
|
||||
|
||||
|
|
|
@ -537,6 +537,17 @@ public:
|
|||
mpDoc->pClass->setViewLanguage(mpDoc, nId, language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Post the text input from external input window, like IME
|
||||
*
|
||||
* @param nType see LibreOfficeKitExtTextInputType
|
||||
* @param pText Text for LOK_EXT_TEXTINPUT
|
||||
*/
|
||||
void postExtTextInputEvent(int nType, const char* pText)
|
||||
{
|
||||
mpDoc->pClass->postExtTextInputEvent(mpDoc, nType, pText);
|
||||
}
|
||||
|
||||
#endif // defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY
|
||||
};
|
||||
|
||||
|
|
|
@ -267,6 +267,11 @@ typedef enum
|
|||
/**
|
||||
* The size and/or the position of the cell cursor changed.
|
||||
*
|
||||
* Payload format: "x, y, width, height, column, row", where the first
|
||||
* 4 numbers are document coordinates, in twips, and the last 2 are table
|
||||
* coordinates starting from 0.
|
||||
* When the cursor is not shown the payload format is the "EMPTY" string.
|
||||
*
|
||||
* Rectangle format is the same as LOK_CALLBACK_INVALIDATE_TILES.
|
||||
*/
|
||||
LOK_CALLBACK_CELL_CURSOR = 17,
|
||||
|
@ -509,11 +514,12 @@ typedef enum
|
|||
* The column/row header is no more valid because of a column/row insertion
|
||||
* or a similar event. Clients must query a new column/row header set.
|
||||
*
|
||||
* The payload says if we are invalidating a row or column header.
|
||||
* The payload says if we are invalidating a row or column header. So,
|
||||
* payload values can be: "row", "column", "all".
|
||||
*/
|
||||
LOK_CALLBACK_INVALIDATE_HEADER = 33,
|
||||
/**
|
||||
* The text content of the address field in Calc.
|
||||
* The text content of the address field in Calc. Eg: "A7"
|
||||
*/
|
||||
LOK_CALLBACK_CELL_ADDRESS = 34,
|
||||
/**
|
||||
|
@ -534,7 +540,32 @@ typedef enum
|
|||
*/
|
||||
LOK_CALLBACK_RULER_UPDATE = 35,
|
||||
/**
|
||||
* Dialog invalidation
|
||||
* Window related callbacks are emitted under this category. It includes
|
||||
* external windows like dialogs, autopopups for now.
|
||||
*
|
||||
* The payload format is:
|
||||
*
|
||||
* {
|
||||
* "id": "unique integer id of the dialog",
|
||||
* "action": "<see below>",
|
||||
* "type": "<see below>"
|
||||
* "rectangle": "x, y, width, height"
|
||||
* }
|
||||
*
|
||||
* "type" tells the type of the window the action is associated with
|
||||
* - "dialog" - window is a dialog
|
||||
* - "child" - window is a floating window (combo boxes, etc.)
|
||||
*
|
||||
* "action" can take following values:
|
||||
* - "created" - window is created in the backend, client can render it now
|
||||
* - "title_changed" - window's title is changed
|
||||
* - "size_changed" - window's size is changed
|
||||
* - "invalidate" - the area as described by "rectangle" is invalidated
|
||||
* Clients must request the new area
|
||||
* - "cursor_invalidate" - cursor is invalidated. New position is in "rectangle"
|
||||
* - "cursor_visible" - cursor visible status is changed. Status is availabe
|
||||
* in "visible" field
|
||||
* - "close" - window is closed
|
||||
*/
|
||||
LOK_CALLBACK_WINDOW = 36,
|
||||
}
|
||||
|
@ -549,6 +580,17 @@ typedef enum
|
|||
}
|
||||
LibreOfficeKitKeyEventType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/// cf. SalEvent::ExtTextInput
|
||||
LOK_EXT_TEXTINPUT,
|
||||
/// cf. SalEvent::ExtTextInputPos
|
||||
LOK_EXT_TEXTINPUT_POS,
|
||||
/// cf. SalEvent::EndExtTextInput
|
||||
LOK_EXT_TEXTINPUT_END
|
||||
}
|
||||
LibreOfficeKitExtTextInputType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/// A pressed gesture has started.
|
||||
|
|
|
@ -134,7 +134,7 @@ namespace LOOLProtocol
|
|||
|
||||
bool getTokenString(const std::string& token, const std::string& name, std::string& value)
|
||||
{
|
||||
if (token.size() > (name.size() + 1) &&
|
||||
if (token.size() >= (name.size() + 1) &&
|
||||
token.compare(0, name.size(), name) == 0 &&
|
||||
token[name.size()] == '=')
|
||||
{
|
||||
|
|
|
@ -227,6 +227,7 @@ bool ChildSession::_handleInput(const char *buffer, int length)
|
|||
tokens[0] == "paste" ||
|
||||
tokens[0] == "insertfile" ||
|
||||
tokens[0] == "key" ||
|
||||
tokens[0] == "textinput" ||
|
||||
tokens[0] == "windowkey" ||
|
||||
tokens[0] == "mouse" ||
|
||||
tokens[0] == "windowmouse" ||
|
||||
|
@ -275,6 +276,10 @@ bool ChildSession::_handleInput(const char *buffer, int length)
|
|||
{
|
||||
return keyEvent(buffer, length, tokens, LokEventTargetEnum::Document);
|
||||
}
|
||||
else if (tokens[0] == "textinput")
|
||||
{
|
||||
return extTextInputEvent(buffer, length, tokens);
|
||||
}
|
||||
else if (tokens[0] == "windowkey")
|
||||
{
|
||||
return keyEvent(buffer, length, tokens, LokEventTargetEnum::Window);
|
||||
|
@ -763,6 +768,28 @@ bool ChildSession::insertFile(const char* /*buffer*/, int /*length*/, const std:
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ChildSession::extTextInputEvent(const char* /*buffer*/, int /*length*/,
|
||||
const std::vector<std::string>& tokens)
|
||||
{
|
||||
int type;
|
||||
std::string text;
|
||||
if (tokens.size() < 3 ||
|
||||
!getTokenKeyword(tokens[1], "type",
|
||||
{{"input", LOK_EXT_TEXTINPUT}, {"end", LOK_EXT_TEXTINPUT_END}},
|
||||
type) ||
|
||||
!getTokenString(tokens[2], "text", text))
|
||||
{
|
||||
sendTextFrame("error: cmd=" + std::string(tokens[0]) + " kind=syntax");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
|
||||
getLOKitDocument()->setView(_viewId);
|
||||
getLOKitDocument()->postExtTextInputEvent(type, text.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChildSession::keyEvent(const char* /*buffer*/, int /*length*/,
|
||||
const std::vector<std::string>& tokens,
|
||||
const LokEventTargetEnum target)
|
||||
|
|
|
@ -188,6 +188,7 @@ private:
|
|||
bool paste(const char* buffer, int length, const std::vector<std::string>& tokens);
|
||||
bool insertFile(const char* buffer, int length, const std::vector<std::string>& tokens);
|
||||
bool keyEvent(const char* buffer, int length, const std::vector<std::string>& tokens, const LokEventTargetEnum target);
|
||||
bool extTextInputEvent(const char* /*buffer*/, int /*length*/, const std::vector<std::string>& tokens);
|
||||
bool dialogKeyEvent(const char* buffer, int length, const std::vector<std::string>& tokens);
|
||||
bool mouseEvent(const char* buffer, int length, const std::vector<std::string>& tokens, const LokEventTargetEnum target);
|
||||
bool unoCommand(const char* buffer, int length, const std::vector<std::string>& tokens);
|
||||
|
|
|
@ -294,15 +294,18 @@ L.Map.Keyboard = L.Handler.extend({
|
|||
|
||||
if (e.type === 'compositionstart' || e.type === 'compositionupdate') {
|
||||
this._isComposing = true; // we are starting composing with IME
|
||||
var txt = '';
|
||||
for (var i = 0; i < e.originalEvent.data.length; i++) {
|
||||
txt += e.originalEvent.data[i];
|
||||
}
|
||||
if (txt) {
|
||||
this._map._socket.sendMessage('textinput type=input text=' + txt);
|
||||
}
|
||||
}
|
||||
|
||||
if (e.type === 'compositionend') {
|
||||
this._isComposing = false; // stop of composing with IME
|
||||
// get the composited char codes
|
||||
var compCharCodes = [];
|
||||
for (var i = 0; i < e.originalEvent.data.length; i++) {
|
||||
compCharCodes.push(e.originalEvent.data[i].charCodeAt());
|
||||
}
|
||||
// clear the input now - best to do this ASAP so the input
|
||||
// is clear for the next word
|
||||
this._map._textArea.value = '';
|
||||
|
@ -350,9 +353,7 @@ L.Map.Keyboard = L.Handler.extend({
|
|||
}
|
||||
if (e.type === 'compositionend') {
|
||||
// Set all keycodes to zero
|
||||
for (var idx = 0; i < compCharCodes.length; ++i) {
|
||||
postEventFn.call(eventObject, 'input', compCharCodes[idx], 0);
|
||||
}
|
||||
this._map._socket.sendMessage('textinput type=end text=void');
|
||||
} else {
|
||||
postEventFn.call(eventObject, 'input', charCode, unoKeyCode);
|
||||
}
|
||||
|
|
|
@ -58,6 +58,9 @@ void WhiteBoxTests::testLOOLProtocolFunctions()
|
|||
CPPUNIT_ASSERT(LOOLProtocol::getTokenString("bar=hello-sailor", "bar", bar));
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("hello-sailor"), bar);
|
||||
|
||||
CPPUNIT_ASSERT(LOOLProtocol::getTokenString("bar=", "bar", bar));
|
||||
CPPUNIT_ASSERT_EQUAL(std::string(""), bar);
|
||||
|
||||
int mumble;
|
||||
std::map<std::string, int> map { { "hello", 1 }, { "goodbye", 2 }, { "adieu", 3 } };
|
||||
|
||||
|
|
|
@ -136,6 +136,7 @@ bool ClientSession::_handleInput(const char *buffer, int length)
|
|||
tokens[0] != "paste" &&
|
||||
tokens[0] != "insertfile" &&
|
||||
tokens[0] != "key" &&
|
||||
tokens[0] != "textinput" &&
|
||||
tokens[0] != "windowkey" &&
|
||||
tokens[0] != "mouse" &&
|
||||
tokens[0] != "windowmouse" &&
|
||||
|
|
Loading…
Reference in a new issue