diff options
author | Caolán McNamara <caolanm@redhat.com> | 2020-12-09 17:28:00 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2020-12-09 20:23:06 +0100 |
commit | 5454d9fc5ed40ed43a8b961b5cb39571ab9df584 (patch) | |
tree | 053e3251f813353589b4e49443ced35aa9de3949 | |
parent | a51e981a1dbf51a25def24d306e075eeeefecba8 (diff) |
tdf#138778 add has_child_focus which considers a related popup a 'child'
Change-Id: Iab23e399f2650ece702fb1f62d1387acca472b42
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107499
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r-- | include/vcl/weld.hxx | 37 | ||||
-rw-r--r-- | svtools/source/control/tabbar.cxx | 13 | ||||
-rw-r--r-- | vcl/inc/salvtables.hxx | 2 | ||||
-rw-r--r-- | vcl/source/app/salvtables.cxx | 5 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtk3gtkinst.cxx | 33 |
5 files changed, 84 insertions, 6 deletions
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx index 98c012378060..d3bdf2ff147f 100644 --- a/include/vcl/weld.hxx +++ b/include/vcl/weld.hxx @@ -89,8 +89,12 @@ protected: public: virtual void set_sensitive(bool sensitive) = 0; virtual bool get_sensitive() const = 0; + + /* visibility */ + virtual void show() = 0; virtual void hide() = 0; + // This function simply calls show() or hide() but is convenient when the // visibility depends on some condition virtual void set_visible(bool visible) @@ -100,17 +104,43 @@ public: else hide(); } - virtual bool get_visible() const = 0; //if this widget visibility is true - virtual bool is_visible() const = 0; //if this widget visibility and all parents is true + + // return if this widget's visibility is true + virtual bool get_visible() const = 0; + + // return if this widget's visibility and that of all its parents is true + virtual bool is_visible() const = 0; + + /* focus */ + + // sets if this widget can own the keyboard focus virtual void set_can_focus(bool bCanFocus) = 0; + + // causes this widget to have the keyboard focus virtual void grab_focus() = 0; + + // returns if this widget has the keyboard focus virtual bool has_focus() const = 0; - virtual bool is_active() const = 0; //if this widget has the focus within the active window + + // if the widget that has focus is a child, which includes toplevel popup + // children, of this widget. So an Entry with an active popup (or dialog) + // has has_child_focus of true, but has_focus of false, while its popup is + // shown + virtual bool has_child_focus() const = 0; + + // return if this widget has the keyboard focus within the active window + // TODO: review if this has any practical difference from has_focus() + virtual bool is_active() const = 0; + virtual void set_has_default(bool has_default) = 0; virtual bool get_has_default() const = 0; + + /* size */ virtual void set_size_request(int nWidth, int nHeight) = 0; virtual Size get_size_request() const = 0; virtual Size get_preferred_size() const = 0; + + /* measure */ virtual float get_approximate_digit_width() const = 0; virtual int get_text_height() const = 0; virtual Size get_pixel_size(const OUString& rText) const = 0; @@ -460,6 +490,7 @@ public: // resized, calling set_centered_on_parent with false will turn this // off again. virtual void set_centered_on_parent(bool bTrackGeometryRequests) = 0; + // returns whether the widget that has focus is within this Window virtual bool has_toplevel_focus() const = 0; virtual void present() = 0; virtual void set_window_state(const OString& rStr) = 0; diff --git a/svtools/source/control/tabbar.cxx b/svtools/source/control/tabbar.cxx index d44dd06d86c0..1beda5faeff6 100644 --- a/svtools/source/control/tabbar.cxx +++ b/svtools/source/control/tabbar.cxx @@ -395,8 +395,9 @@ IMPL_LINK( TabBarEdit, ImplEndEditHdl, void*, pCancel, void ) ResetPostEvent(); maLoseFocusIdle.Stop(); - // do it idle in case we quickly regain focus - if (!m_xEntry->has_focus()) + // We need this query, because the edit gets a losefocus event, + // when it shows the context menu or the insert symbol dialog + if (!m_xEntry->has_focus() && m_xEntry->has_child_focus()) maLoseFocusIdle.Start(); else GetParent()->EndEditMode( pCancel != nullptr ); @@ -406,7 +407,13 @@ IMPL_LINK_NOARG(TabBarEdit, ImplEndTimerHdl, Timer *, void) { if (m_xEntry->has_focus()) return; - GetParent()->EndEditMode( true ); + + // We need this query, because the edit gets a losefocus event, + // when it shows the context menu or the insert symbol dialog + if (m_xEntry->has_child_focus()) + maLoseFocusIdle.Start(); + else + GetParent()->EndEditMode( true ); } namespace { diff --git a/vcl/inc/salvtables.hxx b/vcl/inc/salvtables.hxx index 2fd7198a7b65..0a6cbad7038e 100644 --- a/vcl/inc/salvtables.hxx +++ b/vcl/inc/salvtables.hxx @@ -213,6 +213,8 @@ public: virtual bool is_active() const override; + virtual bool has_child_focus() const override; + virtual void set_has_default(bool has_default) override; virtual bool get_has_default() const override; diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index ccc3757e6718..1289848b7ac5 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -271,6 +271,11 @@ bool SalInstanceWidget::has_focus() const { return m_xWidget->HasFocus(); } bool SalInstanceWidget::is_active() const { return m_xWidget->IsActive(); } +bool SalInstanceWidget::has_child_focus() const +{ + return m_xWidget->HasChildPathFocus(true); +} + void SalInstanceWidget::set_has_default(bool has_default) { m_xWidget->set_property("has-default", OUString::boolean(has_default)); diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx index c4df0cca2855..4cbe5a8b9032 100644 --- a/vcl/unx/gtk3/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/gtk3gtkinst.cxx @@ -2546,6 +2546,39 @@ public: return pTopLevel && gtk_window_is_active(pTopLevel) && has_focus(); } + // is the focus in a child of this widget, where a transient popup attached + // to a widget is considered a child of that widget + virtual bool has_child_focus() const override + { + bool bRet = false; + + GList* pList = gtk_window_list_toplevels(); + + for (GList* pEntry = pList; pEntry; pEntry = pEntry->next) + { + if (!gtk_window_has_toplevel_focus(GTK_WINDOW(pEntry->data))) + continue; + GtkWidget* pFocus = gtk_window_get_focus(GTK_WINDOW(pEntry->data)); + if (pFocus && gtk_widget_is_ancestor(pFocus, m_pWidget)) + { + bRet = true; + break; + } + GtkWidget* pAttachedTo = gtk_window_get_attached_to(GTK_WINDOW(pEntry->data)); + if (!pAttachedTo) + continue; + if (pAttachedTo == m_pWidget || gtk_widget_is_ancestor(pAttachedTo, m_pWidget)) + { + bRet = true; + break; + } + } + + g_list_free(pList); + + return bRet; + } + virtual void set_has_default(bool has_default) override { g_object_set(G_OBJECT(m_pWidget), "has-default", has_default, nullptr); |