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 1db157f706f0e32d2df9970ef3bb558ae9c1d855
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Thu Jul 14 15:52:37 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Tue Jul 19 14:47:43 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
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137219

diff --git a/sw/inc/formatcontentcontrol.hxx b/sw/inc/formatcontentcontrol.hxx
index 19567c27d941..9078b1c81314 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);
+
     virtual 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 =

Reply via email to