vcl/unx/gtk3/gtkinst.cxx |   45 ++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 40 insertions(+), 5 deletions(-)

New commits:
commit 131c1c7da8c567636ca55751e49d24cb6d6c9b9e
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Sun Nov 21 19:53:47 2021 +0000
Commit:     Caolán McNamara <caol...@redhat.com>
CommitDate: Mon Nov 22 09:47:19 2021 +0100

    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/+/125638
    Tested-by: Caolán McNamara <caol...@redhat.com>
    Reviewed-by: Caolán McNamara <caol...@redhat.com>

diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx
index fc99f0986de7..87c40d6ad976 100644
--- a/vcl/unx/gtk3/gtkinst.cxx
+++ b/vcl/unx/gtk3/gtkinst.cxx
@@ -9894,11 +9894,18 @@ GtkPositionType MovePopoverContentsToWindow(GtkWidget* 
pPopover, GtkWindow* pMen
     gtk_container_add(GTK_CONTAINER(pMenuHack), pChild);
     g_object_unref(pChild);
 
-    return show_menu(pAnchor, pMenuHack, rAnchor, ePlace);
+    GtkPositionType eRet = show_menu(pAnchor, pMenuHack, rAnchor, ePlace);
+
+    GdkSurface* pSurface = widget_get_surface(GTK_WIDGET(pMenuHack));
+    g_object_set_data(G_OBJECT(pSurface), "g-lo-InstancePopup", 
GINT_TO_POINTER(true));
+
+    return eRet;
 }
 
 void MoveWindowContentsToPopover(GtkWindow* pMenuHack, GtkWidget* pPopover, 
GtkWidget* pAnchor)
 {
+    bool bHadFocus = gtk_window_has_toplevel_focus(pMenuHack);
+
     do_ungrab(GTK_WIDGET(pMenuHack));
 
     gtk_widget_hide(GTK_WIDGET(pMenuHack));
@@ -9909,6 +9916,9 @@ void MoveWindowContentsToPopover(GtkWindow* pMenuHack, 
GtkWidget* pPopover, GtkW
     gtk_container_add(GTK_CONTAINER(pPopover), pChild);
     g_object_unref(pChild);
 
+    GdkSurface* pSurface = widget_get_surface(GTK_WIDGET(pMenuHack));
+    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(pMenuHack));
 
@@ -9919,6 +9929,15 @@ void MoveWindowContentsToPopover(GtkWindow* pMenuHack, 
GtkWidget* pPopover, GtkW
     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(pAnchor);
+        gtk_widget_grab_focus(pAnchor);
+    }
 }
 
 #endif
@@ -10004,7 +10023,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
@@ -18615,7 +18634,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
@@ -19861,10 +19880,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));
 
@@ -19878,6 +19902,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
         {
@@ -19903,6 +19936,8 @@ private:
 
             GdkRectangle aAnchor {0, 0, 
gtk_widget_get_allocated_width(pComboBox), 
gtk_widget_get_allocated_height(pComboBox) };
             show_menu(pComboBox, m_pMenuWindow, aAnchor, 
weld::Placement::Under);
+            GdkSurface* pSurface = 
widget_get_surface(GTK_WIDGET(m_pMenuWindow));
+            g_object_set_data(G_OBJECT(pSurface), "g-lo-InstancePopup", 
GINT_TO_POINTER(true));
         }
     }
 
@@ -20362,7 +20397,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
@@ -22017,7 +22052,7 @@ private:
         {
             popdown();
         }
-        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

Reply via email to