summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2021-11-21 19:53:47 +0000
committerMichael Stahl <michael.stahl@allotropia.de>2021-11-22 11:51:19 +0100
commitb80b17884962c5e2f50c734f153825c0e37605e2 (patch)
treeaef0968604de67e7a365966c7be3eff277fb58c9 /vcl
parent5853e4d137c3cb535571cba0233b05a48761ac52 (diff)
Related: tdf#145786 cooperate between our own grabs
don't try to workaround a grab if the grab is done by another of our own popups, and on tearing down one of our popups, restore the grab of its parent if that parent was one of our own popups. This typically matters on X where we don't use GtkPopovers (unlike wayland, where Popovers can escape the parent window). Things to test are: writer's watermark dialog: click the color button to get the 1st level popup, then click the combobox to get the 2nd level one, select an entry to return to the 1st level. a) Clicking a valueset element should select that color, not dismiss the popup without selecting a color. b) Clicking the combobox to get the popup again should result in a popup where the focus still follows the mouse (i.e. the 1st level popup doesn't try and steal away the 2nd level grab) sidebar: same scenario as above, except a color popover parented to a sidebar pane and not a dialog. Change-Id: Ib5d765b22b8a9b6b1a7806676c8fe3cfb7709734 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125645 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/unx/gtk3/gtkinst.cxx39
1 files changed, 36 insertions, 3 deletions
diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx
index 78c3b09789c1..4b1cd409fc48 100644
--- a/vcl/unx/gtk3/gtkinst.cxx
+++ b/vcl/unx/gtk3/gtkinst.cxx
@@ -9469,9 +9469,15 @@ private:
return;
if (!get_active())
{
+ bool bHadFocus = gtk_window_has_toplevel_focus(m_pMenuHack);
+
do_ungrab(GTK_WIDGET(m_pMenuHack));
gtk_widget_hide(GTK_WIDGET(m_pMenuHack));
+
+ GdkSurface* pSurface = widget_get_surface(GTK_WIDGET(m_pMenuHack));
+ g_object_set_data(G_OBJECT(pSurface), "g-lo-InstancePopup", GINT_TO_POINTER(false));
+
//put contents back from where the came from
GtkWidget* pChild = gtk_bin_get_child(GTK_BIN(m_pMenuHack));
g_object_ref(pChild);
@@ -9489,6 +9495,15 @@ private:
GtkSalFrame* pFrame = pParent ? GtkSalFrame::getFromWindow(pParent) : nullptr;
if (pFrame)
pFrame->UnblockTooltip();
+
+ if (bHadFocus)
+ {
+ GdkSurface* pParentSurface = pParent ? widget_get_surface(pParent) : nullptr;
+ void* pParentIsPopover = pParentSurface ? g_object_get_data(G_OBJECT(pParentSurface), "g-lo-InstancePopup") : nullptr;
+ if (pParentIsPopover)
+ do_grab(GTK_WIDGET(m_pMenuButton));
+ gtk_widget_grab_focus(GTK_WIDGET(m_pMenuButton));
+ }
}
else
{
@@ -9503,6 +9518,8 @@ private:
g_object_unref(pChild);
GtkPositionType ePosUsed = show_menu(m_pMenuHackAlign ? m_pMenuHackAlign : GTK_WIDGET(m_pMenuButton), m_pMenuHack);
+ GdkSurface* pSurface = widget_get_surface(GTK_WIDGET(m_pMenuHack));
+ g_object_set_data(G_OBJECT(pSurface), "g-lo-InstancePopup", GINT_TO_POINTER(true));
// tdf#132540 keep the placeholder popover on this same side as the replacement menu
gtk_popover_set_position(gtk_menu_button_get_popover(m_pMenuButton), ePosUsed);
}
@@ -9522,7 +9539,7 @@ private:
{
set_active(false);
}
- else
+ else if (!g_object_get_data(G_OBJECT(event->grab_window), "g-lo-InstancePopup")) // another LibreOffice popover took a grab
{
//try and regrab, so when we lose the grab to the menu of the color palette
//combobox we regain it so the color palette doesn't itself disappear on next
@@ -17979,7 +17996,7 @@ private:
{
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_pToggleButton), false);
}
- else
+ else if (!g_object_get_data(G_OBJECT(event->grab_window), "g-lo-InstancePopup")) // another LibreOffice popover took a grab
{
//try and regrab, so when we lose the grab to the menu of the color palette
//combobox we regain it so the color palette doesn't itself disappear on next
@@ -19209,10 +19226,15 @@ private:
m_bHoverSelection = false;
}
+ bool bHadFocus = gtk_window_has_toplevel_focus(m_pMenuWindow);
+
do_ungrab(GTK_WIDGET(m_pMenuWindow));
gtk_widget_hide(GTK_WIDGET(m_pMenuWindow));
+ GdkSurface* pSurface = widget_get_surface(GTK_WIDGET(m_pMenuWindow));
+ g_object_set_data(G_OBJECT(pSurface), "g-lo-InstancePopup", GINT_TO_POINTER(false));
+
// so gdk_window_move_to_rect will work again the next time
gtk_widget_unrealize(GTK_WIDGET(m_pMenuWindow));
@@ -19226,6 +19248,15 @@ private:
GtkSalFrame* pFrame = pParent ? GtkSalFrame::getFromWindow(pParent) : nullptr;
if (pFrame)
pFrame->UnblockTooltip();
+
+ if (bHadFocus)
+ {
+ GdkSurface* pParentSurface = pParent ? widget_get_surface(pParent) : nullptr;
+ void* pParentIsPopover = pParentSurface ? g_object_get_data(G_OBJECT(pParentSurface), "g-lo-InstancePopup") : nullptr;
+ if (pParentIsPopover)
+ do_grab(m_pToggleButton);
+ gtk_widget_grab_focus(m_pToggleButton);
+ }
}
else
{
@@ -19250,6 +19281,8 @@ private:
tree_view_set_cursor(0);
show_menu(pComboBox, m_pMenuWindow);
+ GdkSurface* pSurface = widget_get_surface(GTK_WIDGET(m_pMenuWindow));
+ g_object_set_data(G_OBJECT(pSurface), "g-lo-InstancePopup", GINT_TO_POINTER(true));
}
}
@@ -19707,7 +19740,7 @@ private:
{
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_pToggleButton), false);
}
- else
+ else if (!g_object_get_data(G_OBJECT(event->grab_window), "g-lo-InstancePopup")) // another LibreOffice popover took a grab
{
//try and regrab, so when we lose the grab to the menu of the color palette
//combobox we regain it so the color palette doesn't itself disappear on next