From c56e0c791a79dc414108e1b2fbf0f7eb38657f10 Mon Sep 17 00:00:00 2001 From: Caolán McNamara Date: Thu, 18 Feb 2021 14:56:01 +0000 Subject: move async focus-in/focus-out workaround to known client that needs it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit and for the normal case process immediately. Use-case is the bibliography editor, modified uncommitted entry, click in browser column margin area to select a new row, the entry should commit its old contents to the old row before filling from the new row Change-Id: Ib41d96afcfa86bcd1075b9512d4cfab593afa66d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111152 Tested-by: Jenkins Reviewed-by: Caolán McNamara --- formula/source/ui/dlg/funcutl.cxx | 48 +++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 5 deletions(-) (limited to 'formula') diff --git a/formula/source/ui/dlg/funcutl.cxx b/formula/source/ui/dlg/funcutl.cxx index f64b6aff9bd5..361ec4c9ebaa 100644 --- a/formula/source/ui/dlg/funcutl.cxx +++ b/formula/source/ui/dlg/funcutl.cxx @@ -21,6 +21,7 @@ #include #include +#include #include "ControlHelper.hxx" #include "parawin.hxx" #include @@ -265,9 +266,11 @@ RefEdit::RefEdit(std::unique_ptr xControl) , aIdle("formula RefEdit Idle") , pAnyRefDlg(nullptr) , pLabelWidget(nullptr) + , mpFocusInEvent(nullptr) + , mpFocusOutEvent(nullptr) { - xEntry->connect_focus_in(LINK(this, RefEdit, GetFocus)); - xEntry->connect_focus_out(LINK(this, RefEdit, LoseFocus)); + xEntry->connect_focus_in(LINK(this, RefEdit, GetFocusHdl)); + xEntry->connect_focus_out(LINK(this, RefEdit, LoseFocusHdl)); xEntry->connect_key_press(LINK(this, RefEdit, KeyInputHdl)); xEntry->connect_changed(LINK(this, RefEdit, Modify)); aIdle.SetInvokeHandler( LINK( this, RefEdit, UpdateHdl ) ); @@ -275,6 +278,10 @@ RefEdit::RefEdit(std::unique_ptr xControl) RefEdit::~RefEdit() { + if (mpFocusInEvent) + Application::RemoveUserEvent(mpFocusInEvent); + if (mpFocusOutEvent) + Application::RemoveUserEvent(mpFocusOutEvent); aIdle.ClearInvokeHandler(); aIdle.Stop(); } @@ -355,22 +362,53 @@ void RefEdit::GrabFocus() bool bHadFocus = xEntry->has_focus(); xEntry->grab_focus(); if (!bHadFocus && xEntry->has_focus()) - GetFocus(*xEntry); + GetFocus(); } -IMPL_LINK_NOARG(RefEdit, GetFocus, weld::Widget&, void) +void RefEdit::GetFocus() { maGetFocusHdl.Call(*this); StartUpdateData(); } -IMPL_LINK_NOARG(RefEdit, LoseFocus, weld::Widget&, void) +void RefEdit::LoseFocus() { maLoseFocusHdl.Call(*this); if( pAnyRefDlg ) pAnyRefDlg->HideReference(); } +IMPL_LINK_NOARG(RefEdit, GetFocusHdl, weld::Widget&, void) +{ + // in e.g. function wizard RefEdits we want to select all when we get focus + // but in the gtk case there are pending gtk handlers which change selection + // after our handler, so post our focus in event to happen after those complete + if (mpFocusInEvent) + Application::RemoveUserEvent(mpFocusInEvent); + mpFocusInEvent = Application::PostUserEvent(LINK(this, RefEdit, AsyncFocusInHdl)); +} + +IMPL_LINK_NOARG(RefEdit, LoseFocusHdl, weld::Widget&, void) +{ + // tdf#127262 because focus in is async, focus out must not appear out + // of sequence to focus in + if (mpFocusOutEvent) + Application::RemoveUserEvent(mpFocusOutEvent); + mpFocusOutEvent = Application::PostUserEvent(LINK(this, RefEdit, AsyncFocusOutHdl)); +} + +IMPL_LINK_NOARG(RefEdit, AsyncFocusInHdl, void*, void) +{ + mpFocusInEvent = nullptr; + GetFocus(); +} + +IMPL_LINK_NOARG(RefEdit, AsyncFocusOutHdl, void*, void) +{ + mpFocusOutEvent = nullptr; + LoseFocus(); +} + IMPL_LINK_NOARG(RefEdit, UpdateHdl, Timer *, void) { if( pAnyRefDlg ) -- cgit