Kaydet (Commit) c1bcdf9a authored tarafından Jan-Marek Glogowski's avatar Jan-Marek Glogowski

Qt5 IM handle (spurious?) all-empty IM events

2nd attempt to fix the bug described in commit 00221089 ("Qt5
IM allow committing empty strings") and various siblings of it.
This also reverts it.

What I see is calls with "all-empty" events (preedit, commit and
replacementLength() == 0; no QInputMethodEvent::Attribute), some
from QIBusPlatformInputContext::updatePreeditText.

There are various Writer document edit states with (selected)
text, undo, cursor position and focus changes to other windows via
Ctrl+Tab, which will result in inputMethodEvent calls totally in
contrast to the expected text state, all somehow always related to
all-empty events. They currently result in wrongly deleted
selected text, change of selection, cursor movement or general
change of text from old preedit. Most time on focus out / window
change, some times at first meta-key press after focus in.

This patch tries hard not to corrupt Writers edit state with these
all-empty events. No idea if this is some bug on LO's qt5 side or
expected, but KDE kate and VCL gtk3 and gen work fine, so I assume
Qt's behaviour is correct. FWIW gtk3 also does some extended IM
handling with focus, so probably this is the Qt equivalent of it.
But then I couldn't find some eqivalent code in Qt's source code.
I actually expected an even more complex solution (if this really
fixes all cases).

Works for a multitude of tests I tried to come up with, but is
quite probably not the final fix to this, as qt5 current doesn't
handle replacementStart() and replacementLength() at all.
Also never saw a call to Qt5Frame::EndExtTextInput.

Change-Id: I4210e0588041cfb4d80dbdfdb937e430a5f7cbfb
Reviewed-on: https://gerrit.libreoffice.org/71988
Tested-by: Jenkins
Reviewed-by: 's avatarJan-Marek Glogowski <glogow@fbihome.de>
üst c5c42529
......@@ -43,6 +43,7 @@ class Qt5Widget : public QWidget
Q_OBJECT
Qt5Frame& m_rFrame;
bool m_bNonEmptyIMPreeditSeen;
bool handleKeyEvent(QKeyEvent*, bool);
void handleMouseButtonEvent(QMouseEvent*, bool);
......@@ -51,6 +52,7 @@ class Qt5Widget : public QWidget
virtual void focusInEvent(QFocusEvent*) override;
virtual void focusOutEvent(QFocusEvent*) override;
// keyPressEvent(QKeyEvent*) is handled via event(QEvent*); see comment
virtual void keyReleaseEvent(QKeyEvent*) override;
virtual void mouseMoveEvent(QMouseEvent*) override;
virtual void mousePressEvent(QMouseEvent*) override;
......@@ -76,6 +78,7 @@ public:
Qt5Frame& getFrame() const { return m_rFrame; }
void startDrag(sal_Int8 nSourceActions);
void endExtTextInput();
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -723,7 +723,9 @@ void Qt5Frame::SetInputContext(SalInputContext* pContext)
void Qt5Frame::EndExtTextInput(EndExtTextInputFlags /*nFlags*/)
{
// TODO fwd to IM handler
Qt5Widget* pQt5Widget = static_cast<Qt5Widget*>(m_pQWidget);
if (pQt5Widget)
pQt5Widget->endExtTextInput();
}
OUString Qt5Frame::GetKeyName(sal_uInt16 nKeyCode)
......
......@@ -433,7 +433,11 @@ void Qt5Widget::keyReleaseEvent(QKeyEvent* pEvent)
void Qt5Widget::focusInEvent(QFocusEvent*) { m_rFrame.CallCallback(SalEvent::GetFocus, nullptr); }
void Qt5Widget::focusOutEvent(QFocusEvent*) { m_rFrame.CallCallback(SalEvent::LoseFocus, nullptr); }
void Qt5Widget::focusOutEvent(QFocusEvent*)
{
endExtTextInput();
m_rFrame.CallCallback(SalEvent::LoseFocus, nullptr);
}
void Qt5Widget::showTooltip(const OUString& rTooltip)
{
......@@ -444,6 +448,7 @@ void Qt5Widget::showTooltip(const OUString& rTooltip)
Qt5Widget::Qt5Widget(Qt5Frame& rFrame, Qt::WindowFlags f)
: QWidget(Q_NULLPTR, f)
, m_rFrame(rFrame)
, m_bNonEmptyIMPreeditSeen(false)
{
create();
setMouseTracking(true);
......@@ -475,13 +480,14 @@ void Qt5Widget::inputMethodEvent(QInputMethodEvent* pEvent)
aInputEvent.mpTextAttr = nullptr;
aInputEvent.mnCursorFlags = 0;
if (!pEvent->commitString().isNull())
vcl::DeletionListener aDel(&m_rFrame);
if (!pEvent->commitString().isEmpty())
{
vcl::DeletionListener aDel(&m_rFrame);
aInputEvent.maText = toOUString(pEvent->commitString());
aInputEvent.mnCursorPos = aInputEvent.maText.getLength();
m_rFrame.CallCallback(SalEvent::ExtTextInput, &aInputEvent);
pEvent->accept();
if (!aDel.isDeleted())
m_rFrame.CallCallback(SalEvent::ExtTextInput, &aInputEvent);
if (!aDel.isDeleted())
m_rFrame.CallCallback(SalEvent::EndExtTextInput, nullptr);
}
......@@ -531,9 +537,18 @@ void Qt5Widget::inputMethodEvent(QInputMethodEvent* pEvent)
}
}
m_rFrame.CallCallback(SalEvent::ExtTextInput, &aInputEvent);
pEvent->accept();
const bool bIsEmpty = aInputEvent.maText.isEmpty();
if (m_bNonEmptyIMPreeditSeen || !bIsEmpty)
{
if (!aDel.isDeleted())
m_rFrame.CallCallback(SalEvent::ExtTextInput, &aInputEvent);
if (!aDel.isDeleted() && bIsEmpty)
m_rFrame.CallCallback(SalEvent::EndExtTextInput, nullptr);
m_bNonEmptyIMPreeditSeen = !bIsEmpty;
}
}
pEvent->accept();
}
QVariant Qt5Widget::inputMethodQuery(Qt::InputMethodQuery property) const
......@@ -552,4 +567,13 @@ QVariant Qt5Widget::inputMethodQuery(Qt::InputMethodQuery property) const
}
}
void Qt5Widget::endExtTextInput()
{
if (m_bNonEmptyIMPreeditSeen)
{
m_rFrame.CallCallback(SalEvent::EndExtTextInput, nullptr);
m_bNonEmptyIMPreeditSeen = false;
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment