Blob Blame History Raw
From 7ee77f157c166c1e7ddb6c2215518119fb6175df Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com>
Date: Thu, 5 May 2016 15:19:24 +0100
Subject: [PATCH] gtk3: New Folder dialog from Templates dialog doesn't get
 keyboard focus
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

ctrl+shift+N, and click new folder, no keyboard input is accepted.

The dialogs don't get keyboard events, because the keyboard events
go to the top level window because of...

commit 011ce226e89ecabaf621603d692547c88061eaba
Author: Caolán McNamara <caolanm@redhat.com>
Date:   Tue Jan 19 13:22:10 2016 +0000

    Resolves: tdf#99604 ungrab modal dialogs

(should be tdf#96604) which stripped away the grab from the sub dialog

but I did that because menu dropdowns from comboboxes inside modal
dialogs didn't receive mouse focus otherwise.

I had set our "modal" dialogs to be truly modal and triggering that
problem with

commit 8d5822983e9b6a1e04874ce4d2c807fd0cf1ee04
Author: Caolán McNamara <caolanm@redhat.com>
Date:   Mon Dec 14 11:36:50 2015 +0000

    Related: rhbz#1290014 gtk3: use gtk_window_set_modal on modal dialogs

    which makes modal dialogs (which are most of them) place correctly
    under wayland. Modeless ones are still uselessly shoved far to the
    left, but this makes things near usable and gives the same "graying
    into the bg" effect for the main window as other gtk apps

which I still contend is "a good thing"

if we stop removing the grab from the modal dialog, then we still have
the problem that the menu dropdowns from comboboxes inside modal dialogs
don't receive mouse focus otherwise.

After trying to add/remove grabs around showing/hiding menus we run
into another pit of trouble

(commit 72e6a1365cb08986b542a5beb797634bca62d85b
Author: Caolán McNamara <caolanm@redhat.com>
Date:   Wed May 4 16:29:35 2016 +0100)

so, lets save the widget that has the grab before showing our first
menu, clear the grab, and restore it on hiding the first menu again.

and still ditch that metacity hack around thing at this point too

I truly hate this crap

Change-Id: If10e758585f156b33680b8d40355302cc1ae72f3

gtk3: use window groups so modal dialog are modal to their toplevel frame only

so e.g. launching help from a modal dialog gives a new toplevel window
which is not blocked by the modal dialog on the other window.

likesize can go from one blocked e.g. writer window to calc and type away in
there happily

Change-Id: Id9376b393514e91dfd667dfce132f1f37367084e
(cherry picked from commit c80d34ad551efe858c47445b13370aa8223357c7)

gtk3: use gtk_window_group_get_current_grab instead of gtk_grab_get_current

now that we are using window groups, otherwise the problem of tdf#99604
comes back

Change-Id: I7a940ea72bfd7fd4a7f68f1e60395d5014ce155c
(cherry picked from commit 9b49e1817d4d045b724aed6267f8f00c6bf295cc)

Resolves: tdf#100327 gtk3 fpicker yes/no dialog modal trouble

not sure why we ever hid the file dialog when putting up the
yes/no dialog. So lets just do the more apparently sensible thing
on the gtk3 path and leave gtk2 alone.

Probably fallout from using window groups

(cherry picked from commit e50caebc02ee2045a38a39b4a4c644da0d678541)
(cherry picked from commit 83b7c1ae8068787212f757b9c8b9c317537a2dd2)

Change-Id: I4d0e8fae9568b050b674cf6ef4d8c88e65dd2ca1
---
 cui/source/customize/cfg.cxx             |  4 +--
 cui/source/customize/selector.cxx        | 15 ++-------
 cui/source/inc/selector.hxx              |  2 +-
 vcl/inc/unx/gtk/gtkframe.hxx             |  1 +
 vcl/unx/gtk/fpicker/SalGtkFilePicker.cxx |  4 +++
 vcl/unx/gtk/fpicker/SalGtkPicker.cxx     |  2 ++
 vcl/unx/gtk3/gtk3gtkframe.cxx            | 57 +++++++++++++++++---------------
 7 files changed, 43 insertions(+), 42 deletions(-)

diff --git a/cui/source/customize/cfg.cxx b/cui/source/customize/cfg.cxx
index 018cf39..72e8af5 100644
--- a/cui/source/customize/cfg.cxx
+++ b/cui/source/customize/cfg.cxx
@@ -2816,7 +2816,7 @@ IMPL_LINK_NOARG_TYPED( SvxMenuConfigPage, AddCommandsHdl, Button *, void )
 
     m_pSelectorDlg->SetImageProvider( GetSaveInData() );
 
-    m_pSelectorDlg->Show();
+    m_pSelectorDlg->Execute();
 }
 
 SaveInData* SvxMenuConfigPage::CreateSaveInData(
@@ -4702,7 +4702,7 @@ IMPL_LINK_NOARG_TYPED( SvxToolbarConfigPage, AddCommandsHdl, Button *, void )
 
     m_pSelectorDlg->SetImageProvider( GetSaveInData() );
 
-    m_pSelectorDlg->Show();
+    m_pSelectorDlg->Execute();
 }
 
 IMPL_LINK_NOARG_TYPED( SvxToolbarConfigPage, AddFunctionHdl, SvxScriptSelectorDialog&, void )
diff --git a/cui/source/customize/selector.cxx b/cui/source/customize/selector.cxx
index 28fbd87..5d76bb9 100644
--- a/cui/source/customize/selector.cxx
+++ b/cui/source/customize/selector.cxx
@@ -874,7 +874,7 @@ void SvxConfigGroupListBox::RequestingChildren( SvTreeListEntry *pEntry )
 
 SvxScriptSelectorDialog::SvxScriptSelectorDialog(
     vcl::Window* pParent, bool bShowSlots, const Reference< frame::XFrame >& xFrame)
-    : ModelessDialog(pParent, "MacroSelectorDialog", "cui/ui/macroselectordialog.ui")
+    : ModalDialog(pParent, "MacroSelectorDialog", "cui/ui/macroselectordialog.ui")
     , m_bShowSlots(bShowSlots)
 {
     get<FixedText>("libraryft")->Show(!m_bShowSlots);
@@ -934,7 +934,7 @@ void SvxScriptSelectorDialog::dispose()
     m_pOKButton.clear();
     m_pCancelButton.clear();
     m_pDescriptionText.clear();
-    ModelessDialog::dispose();
+    ModalDialog::dispose();
 }
 
 IMPL_LINK_TYPED( SvxScriptSelectorDialog, SelectHdl, SvTreeListBox*, pCtrl, void )
@@ -982,16 +982,7 @@ IMPL_LINK_TYPED( SvxScriptSelectorDialog, ClickHdl, Button *, pButton, void )
 {
     if (pButton == m_pCancelButton)
     {
-        // If we are displaying Slot API commands then the dialog is being
-        // run from Tools/Configure and we should not close it, just hide it
-        if ( !m_bShowSlots )
-        {
-            EndDialog();
-        }
-        else
-        {
-            Hide();
-        }
+        EndDialog();
     }
     else if (pButton == m_pOKButton)
     {
diff --git a/cui/source/inc/selector.hxx b/cui/source/inc/selector.hxx
index 2f6b194..ad4bfa9 100644
--- a/cui/source/inc/selector.hxx
+++ b/cui/source/inc/selector.hxx
@@ -172,7 +172,7 @@ public:
         { m_pImageProvider = provider; }
 };
 
-class SvxScriptSelectorDialog : public ModelessDialog
+class SvxScriptSelectorDialog : public ModalDialog
 {
     VclPtr<FixedText>                      m_pDialogDescription;
     VclPtr<SvxConfigGroupListBox>          m_pCategories;
diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx
index eaa222f..871ddd3 100644
--- a/vcl/inc/unx/gtk/gtkframe.hxx
+++ b/vcl/inc/unx/gtk/gtkframe.hxx
@@ -298,6 +298,7 @@ class GtkSalFrame : public SalFrame
     static GdkNativeWindow findTopLevelSystemWindow( GdkNativeWindow aWindow );
 
     static int m_nFloats;
+    static std::vector<GtkWidget*> m_aGrabWidgetsBeforeShowFloat;
 
     bool isFloatGrabWindow() const
     {
diff --git a/vcl/unx/gtk/fpicker/SalGtkFilePicker.cxx b/vcl/unx/gtk/fpicker/SalGtkFilePicker.cxx
index 9798639..b6b60f6 100644
--- a/vcl/unx/gtk/fpicker/SalGtkFilePicker.cxx
+++ b/vcl/unx/gtk/fpicker/SalGtkFilePicker.cxx
@@ -1012,8 +1012,12 @@ sal_Int16 SAL_CALL SalGtkFilePicker::execute() throw( uno::RuntimeException, std
                             gtk_window_set_title( GTK_WINDOW( dlg ),
                                 OUStringToOString(getResString(FILE_PICKER_TITLE_SAVE ),
                                 RTL_TEXTENCODING_UTF8 ).getStr() );
+#if GTK_CHECK_VERSION(3,0,0)
+                            gtk_window_set_transient_for(GTK_WINDOW(dlg), GTK_WINDOW(m_pDialog));
+#else
                             if (pParent)
                                 gtk_window_set_transient_for(GTK_WINDOW(dlg), pParent);
+#endif
                             RunDialog* pAnotherDialog = new RunDialog(dlg, xToolkit, xDesktop);
                             uno::Reference < awt::XTopWindowListener > xAnotherLifeCycle(pAnotherDialog);
                             btn = pAnotherDialog->run();
diff --git a/vcl/unx/gtk/fpicker/SalGtkPicker.cxx b/vcl/unx/gtk/fpicker/SalGtkPicker.cxx
index 26b2740..06e9550 100644
--- a/vcl/unx/gtk/fpicker/SalGtkPicker.cxx
+++ b/vcl/unx/gtk/fpicker/SalGtkPicker.cxx
@@ -183,8 +183,10 @@ gint RunDialog::run()
     if (mxToolkit.is())
         mxToolkit->removeTopWindowListener(this);
 
+#if !GTK_CHECK_VERSION(3,0,0)
     if (nStatus != 1)   //PLAY
         gtk_widget_hide( mpDialog );
+#endif
 
     return nStatus;
 }
diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx
index 6363815..1569691 100644
--- a/vcl/unx/gtk3/gtk3gtkframe.cxx
+++ b/vcl/unx/gtk3/gtk3gtkframe.cxx
@@ -106,6 +106,7 @@
 using namespace com::sun::star;
 
 int GtkSalFrame::m_nFloats = 0;
+std::vector<GtkWidget*> GtkSalFrame::m_aGrabWidgetsBeforeShowFloat;
 
 #if defined ENABLE_GMENU_INTEGRATION
 static GDBusConnection* pSessionBus = nullptr;
@@ -834,8 +835,10 @@ GtkSalFrame::~GtkSalFrame()
 
     InvalidateGraphics();
 
-    if( m_pParent )
+    if (m_pParent)
+    {
         m_pParent->m_aChildren.remove( this );
+    }
 
     getDisplay()->deregisterFrame( this );
 
@@ -1212,6 +1215,12 @@ void GtkSalFrame::Init( SalFrame* pParent, SalFrameStyleFlags nStyle )
         if (!(m_pParent->m_nStyle & SalFrameStyleFlags::PLUG))
             gtk_window_set_transient_for( GTK_WINDOW(m_pWindow), GTK_WINDOW(m_pParent->m_pWindow) );
         m_pParent->m_aChildren.push_back( this );
+        gtk_window_group_add_window(gtk_window_get_group(GTK_WINDOW(m_pParent->m_pWindow)), GTK_WINDOW(m_pWindow));
+    }
+    else
+    {
+        gtk_window_group_add_window(gtk_window_group_new(), GTK_WINDOW(m_pWindow));
+        g_object_unref(gtk_window_get_group(GTK_WINDOW(m_pWindow)));
     }
 
     InitCommon();
@@ -1447,21 +1456,6 @@ void GtkSalFrame::Show( bool bVisible, bool bNoActivate )
                 SetDefaultSize();
             setMinMaxSize();
 
-            if( isFloatGrabWindow() &&
-                m_pParent &&
-                m_nFloats == 0 &&
-                ! getDisplay()->GetCaptureFrame() )
-            {
-                /* #i63086#
-                 * outsmart Metacity's "focus:mouse" mode
-                 * which insists on taking the focus from the document
-                 * to the new float. Grab focus to parent frame BEFORE
-                 * showing the float (cannot grab it to the float
-                 * before show).
-                 */
-                 m_pParent->grabPointer( true, true );
-            }
-
             if( ! bNoActivate && (m_nStyle & SalFrameStyleFlags::TOOLWINDOW) )
                 m_bSetFocusOnMap = true;
 
@@ -1472,6 +1466,13 @@ void GtkSalFrame::Show( bool bVisible, bool bNoActivate )
                 m_nFloats++;
                 if( ! getDisplay()->GetCaptureFrame() && m_nFloats == 1 )
                 {
+                    GtkWindowGroup *pWindowGroup = gtk_window_get_group(GTK_WINDOW(m_pWindow));
+                    GtkWidget* pGrabWidgetBeforeShowFloat;
+                    while ((pGrabWidgetBeforeShowFloat = gtk_window_group_get_current_grab(pWindowGroup)))
+                    {
+                        m_aGrabWidgetsBeforeShowFloat.push_back(pGrabWidgetBeforeShowFloat);
+                        gtk_grab_remove(pGrabWidgetBeforeShowFloat);
+                    }
                     grabPointer(true, true);
                     GtkSalFrame *pKeyboardFrame = m_pParent ? m_pParent : this;
                     pKeyboardFrame->grabKeyboard(true);
@@ -1493,6 +1494,9 @@ void GtkSalFrame::Show( bool bVisible, bool bNoActivate )
                     GtkSalFrame *pKeyboardFrame = m_pParent ? m_pParent : this;
                     pKeyboardFrame->grabKeyboard(false);
                     grabPointer(false);
+                    for (auto i = m_aGrabWidgetsBeforeShowFloat.rbegin(); i != m_aGrabWidgetsBeforeShowFloat.rend(); ++i)
+                        gtk_grab_add(*i);
+                    m_aGrabWidgetsBeforeShowFloat.clear();
                 }
             }
             gtk_widget_hide( m_pWindow );
@@ -2376,11 +2380,17 @@ const SystemEnvData* GtkSalFrame::GetSystemData() const
 
 void GtkSalFrame::SetParent( SalFrame* pNewParent )
 {
-    if( m_pParent )
-        m_pParent->m_aChildren.remove( this );
+    if (m_pParent)
+    {
+        gtk_window_group_remove_window(gtk_window_get_group(GTK_WINDOW(m_pParent->m_pWindow)), GTK_WINDOW(m_pWindow));
+        m_pParent->m_aChildren.remove(this);
+    }
     m_pParent = static_cast<GtkSalFrame*>(pNewParent);
-    if( m_pParent )
-        m_pParent->m_aChildren.push_back( this );
+    if (m_pParent)
+    {
+        m_pParent->m_aChildren.push_back(this);
+        gtk_window_group_add_window(gtk_window_get_group(GTK_WINDOW(m_pParent->m_pWindow)), GTK_WINDOW(m_pWindow));
+    }
     if( ! isChild() )
         gtk_window_set_transient_for( GTK_WINDOW(m_pWindow),
                                       (m_pParent && ! m_pParent->isChild(true,false)) ? GTK_WINDOW(m_pParent->m_pWindow) : nullptr
@@ -2431,13 +2441,6 @@ void GtkSalFrame::SetModal(bool bModal)
     if (!m_pWindow)
         return;
     gtk_window_set_modal(GTK_WINDOW(m_pWindow), bModal);
-    if (bModal)
-    {
-        //gtk_window_set_modal bTrue adds a grab, so ungrab here. Quite
-        //possibly we should alternatively call grab_add grab_ungrab on
-        //show/hide of menus ?
-        gtk_grab_remove(m_pWindow);
-    }
 }
 
 gboolean GtkSalFrame::signalTooltipQuery(GtkWidget*, gint /*x*/, gint /*y*/,
-- 
2.7.4