diff options
author | Caolán McNamara <caolanm@redhat.com> | 2021-02-18 14:56:01 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2021-02-18 21:04:32 +0100 |
commit | c56e0c791a79dc414108e1b2fbf0f7eb38657f10 (patch) | |
tree | 902ac8d87e5e8021353720467dbe379fbc46f546 /formula/source | |
parent | 28557f54caf924240e6d698a9d2f1e2bc1cf3ab4 (diff) |
move async focus-in/focus-out workaround to known client that needs it
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 <caolanm@redhat.com>
Diffstat (limited to 'formula/source')
-rw-r--r-- | formula/source/ui/dlg/funcutl.cxx | 48 |
1 files changed, 43 insertions, 5 deletions
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 <formula/funcutl.hxx> #include <formula/IControlReferenceHandler.hxx> +#include <vcl/svapp.hxx> #include "ControlHelper.hxx" #include "parawin.hxx" #include <strings.hrc> @@ -265,9 +266,11 @@ RefEdit::RefEdit(std::unique_ptr<weld::Entry> 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<weld::Entry> 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 ) |