sw/inc/formatcontentcontrol.hxx | 3 ++ sw/qa/core/txtnode/txtnode.cxx | 29 ++++++++++++++++++++++++++ sw/source/core/txtnode/attrcontentcontrol.cxx | 10 ++++++++ sw/source/uibase/docvw/edtwin.cxx | 23 ++++++++++++++++++++ 4 files changed, 65 insertions(+)
New commits: commit c6eb8713438d1ba791fc858c8dc6e3d4d6583e0a Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Thu Jul 14 15:52:37 2022 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Thu Jul 14 19:05:27 2022 +0200 sw content control, checkbox: allow toggling via the keyboard Toggling a checkbox content control was only possible by clicking on it with the mouse, which breaks accessiblity. Trying to type into a checkbox content control triggered the read-only popup (which is good), but there was no special handling for the space character, which is meant to toggle the checkbox. Fix the problem by adding a way to query if the current keycode is meant to interact with the content control, and if so, invoke GotoContentControl() from SwEditWin::KeyInput(), similar to how the click handler already did this already. This only handles checkboxes, but other types can be addressed in a follow-up commits similarly. Change-Id: I5c88f2e2f1c2d0f4b28f2ce0b6b1c75b14b7d67c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137082 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/sw/inc/formatcontentcontrol.hxx b/sw/inc/formatcontentcontrol.hxx index 82f4fca9e2be..839a7919ee6b 100644 --- a/sw/inc/formatcontentcontrol.hxx +++ b/sw/inc/formatcontentcontrol.hxx @@ -272,6 +272,9 @@ public: std::optional<double> GetSelectedDate() const { return m_oSelectedDate; } + /// Should this character (during key input) interact with the content control? + bool IsInteractingCharacter(sal_Unicode cCh); + void dumpAsXml(xmlTextWriterPtr pWriter) const; void SetDataBindingPrefixMappings(const OUString& rDataBindingPrefixMappings) diff --git a/sw/qa/core/txtnode/txtnode.cxx b/sw/qa/core/txtnode/txtnode.cxx index ad44a12f7c9b..55fece606c4c 100644 --- a/sw/qa/core/txtnode/txtnode.cxx +++ b/sw/qa/core/txtnode/txtnode.cxx @@ -25,6 +25,11 @@ #include <unotxdoc.hxx> #include <docsh.hxx> #include <formatcontentcontrol.hxx> +#include <view.hxx> +#include <edtwin.hxx> +#include <txatbase.hxx> +#include <ndtxt.hxx> +#include <textcontentcontrol.hxx> constexpr OUStringLiteral DATA_DIRECTORY = u"/sw/qa/core/txtnode/data/"; @@ -220,6 +225,30 @@ CPPUNIT_TEST_FIXTURE(SwCoreTxtnodeTest, testInsertDropDownContentControlTwice) pWrtShell->InsertContentControl(SwContentControlType::DROP_DOWN_LIST); } +CPPUNIT_TEST_FIXTURE(SwCoreTxtnodeTest, testCheckboxContentControlKeyboard) +{ + // Given an already selected checkbox content control: + SwDoc* pDoc = createSwDoc(); + SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + pWrtShell->InsertContentControl(SwContentControlType::CHECKBOX); + SwEditWin& rEditWin = pWrtShell->GetView().GetEditWin(); + + // When pressing space on the keyboard: + KeyEvent aKeyEvent(' ', KEY_SPACE); + rEditWin.KeyInput(aKeyEvent); + + // Then make sure the state is toggled: + SwTextNode* pTextNode = pWrtShell->GetCursor()->GetNode().GetTextNode(); + SwTextAttr* pAttr = pTextNode->GetTextAttrForCharAt(0, RES_TXTATR_CONTENTCONTROL); + auto pTextContentControl = static_txtattr_cast<SwTextContentControl*>(pAttr); + auto& rFormatContentControl + = static_cast<SwFormatContentControl&>(pTextContentControl->GetAttr()); + std::shared_ptr<SwContentControl> pContentControl = rFormatContentControl.GetContentControl(); + // Without the accompanying fix in place, this test would have failed, because the state + // remained unchanged. + CPPUNIT_ASSERT(pContentControl->GetChecked()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/txtnode/attrcontentcontrol.cxx b/sw/source/core/txtnode/attrcontentcontrol.cxx index 4b5ff4554f15..1f3d26f6c2b6 100644 --- a/sw/source/core/txtnode/attrcontentcontrol.cxx +++ b/sw/source/core/txtnode/attrcontentcontrol.cxx @@ -301,6 +301,16 @@ double SwContentControl::GetCurrentDateValue() const return dCurrentDate; } +bool SwContentControl::IsInteractingCharacter(sal_Unicode cCh) +{ + if (GetCheckbox()) + { + return cCh == ' '; + } + + return false; +} + void SwContentControl::dumpAsXml(xmlTextWriterPtr pWriter) const { (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwContentControl")); diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx index 420da9d0b295..b81ac632a0e5 100644 --- a/sw/source/uibase/docvw/edtwin.cxx +++ b/sw/source/uibase/docvw/edtwin.cxx @@ -2414,6 +2414,29 @@ KEYINPUT_CHECKTABLE_INSDEL: aCh = '\t'; [[fallthrough]]; case SwKeyState::InsChar: + if (rSh.CursorInsideContentControl()) + { + const SwPosition* pStart = rSh.GetCursor()->Start(); + SwTextNode* pTextNode = pStart->nNode.GetNode().GetTextNode(); + if (pTextNode) + { + sal_Int32 nIndex = pStart->nContent.GetIndex(); + SwTextAttr* pAttr = pTextNode->GetTextAttrAt(nIndex, RES_TXTATR_CONTENTCONTROL, SwTextNode::PARENT); + if (pAttr) + { + auto pTextContentControl = static_txtattr_cast<SwTextContentControl*>(pAttr); + const SwFormatContentControl& rFormatContentControl = pTextContentControl->GetContentControl(); + std::shared_ptr<SwContentControl> pContentControl = rFormatContentControl.GetContentControl(); + if (pContentControl->IsInteractingCharacter(aCh)) + { + rSh.GotoContentControl(rFormatContentControl); + eKeyState = SwKeyState::End; + break; + } + } + } + } + if (rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT) { ::sw::mark::ICheckboxFieldmark* pFieldmark =