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 ...@@ -43,6 +43,7 @@ class Qt5Widget : public QWidget
Q_OBJECT Q_OBJECT
Qt5Frame& m_rFrame; Qt5Frame& m_rFrame;
bool m_bNonEmptyIMPreeditSeen;
bool handleKeyEvent(QKeyEvent*, bool); bool handleKeyEvent(QKeyEvent*, bool);
void handleMouseButtonEvent(QMouseEvent*, bool); void handleMouseButtonEvent(QMouseEvent*, bool);
...@@ -51,6 +52,7 @@ class Qt5Widget : public QWidget ...@@ -51,6 +52,7 @@ class Qt5Widget : public QWidget
virtual void focusInEvent(QFocusEvent*) override; virtual void focusInEvent(QFocusEvent*) override;
virtual void focusOutEvent(QFocusEvent*) override; virtual void focusOutEvent(QFocusEvent*) override;
// keyPressEvent(QKeyEvent*) is handled via event(QEvent*); see comment
virtual void keyReleaseEvent(QKeyEvent*) override; virtual void keyReleaseEvent(QKeyEvent*) override;
virtual void mouseMoveEvent(QMouseEvent*) override; virtual void mouseMoveEvent(QMouseEvent*) override;
virtual void mousePressEvent(QMouseEvent*) override; virtual void mousePressEvent(QMouseEvent*) override;
...@@ -76,6 +78,7 @@ public: ...@@ -76,6 +78,7 @@ public:
Qt5Frame& getFrame() const { return m_rFrame; } Qt5Frame& getFrame() const { return m_rFrame; }
void startDrag(sal_Int8 nSourceActions); void startDrag(sal_Int8 nSourceActions);
void endExtTextInput();
}; };
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -723,7 +723,9 @@ void Qt5Frame::SetInputContext(SalInputContext* pContext) ...@@ -723,7 +723,9 @@ void Qt5Frame::SetInputContext(SalInputContext* pContext)
void Qt5Frame::EndExtTextInput(EndExtTextInputFlags /*nFlags*/) 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) OUString Qt5Frame::GetKeyName(sal_uInt16 nKeyCode)
......
...@@ -433,7 +433,11 @@ void Qt5Widget::keyReleaseEvent(QKeyEvent* pEvent) ...@@ -433,7 +433,11 @@ void Qt5Widget::keyReleaseEvent(QKeyEvent* pEvent)
void Qt5Widget::focusInEvent(QFocusEvent*) { m_rFrame.CallCallback(SalEvent::GetFocus, nullptr); } 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) void Qt5Widget::showTooltip(const OUString& rTooltip)
{ {
...@@ -444,6 +448,7 @@ void Qt5Widget::showTooltip(const OUString& rTooltip) ...@@ -444,6 +448,7 @@ void Qt5Widget::showTooltip(const OUString& rTooltip)
Qt5Widget::Qt5Widget(Qt5Frame& rFrame, Qt::WindowFlags f) Qt5Widget::Qt5Widget(Qt5Frame& rFrame, Qt::WindowFlags f)
: QWidget(Q_NULLPTR, f) : QWidget(Q_NULLPTR, f)
, m_rFrame(rFrame) , m_rFrame(rFrame)
, m_bNonEmptyIMPreeditSeen(false)
{ {
create(); create();
setMouseTracking(true); setMouseTracking(true);
...@@ -475,13 +480,14 @@ void Qt5Widget::inputMethodEvent(QInputMethodEvent* pEvent) ...@@ -475,13 +480,14 @@ void Qt5Widget::inputMethodEvent(QInputMethodEvent* pEvent)
aInputEvent.mpTextAttr = nullptr; aInputEvent.mpTextAttr = nullptr;
aInputEvent.mnCursorFlags = 0; 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.maText = toOUString(pEvent->commitString());
aInputEvent.mnCursorPos = aInputEvent.maText.getLength(); aInputEvent.mnCursorPos = aInputEvent.maText.getLength();
m_rFrame.CallCallback(SalEvent::ExtTextInput, &aInputEvent); if (!aDel.isDeleted())
pEvent->accept(); m_rFrame.CallCallback(SalEvent::ExtTextInput, &aInputEvent);
if (!aDel.isDeleted()) if (!aDel.isDeleted())
m_rFrame.CallCallback(SalEvent::EndExtTextInput, nullptr); m_rFrame.CallCallback(SalEvent::EndExtTextInput, nullptr);
} }
...@@ -531,9 +537,18 @@ void Qt5Widget::inputMethodEvent(QInputMethodEvent* pEvent) ...@@ -531,9 +537,18 @@ void Qt5Widget::inputMethodEvent(QInputMethodEvent* pEvent)
} }
} }
m_rFrame.CallCallback(SalEvent::ExtTextInput, &aInputEvent); const bool bIsEmpty = aInputEvent.maText.isEmpty();
pEvent->accept(); 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 QVariant Qt5Widget::inputMethodQuery(Qt::InputMethodQuery property) const
...@@ -552,4 +567,13 @@ 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: */ /* 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