[Libreoffice-commits] core.git: Branch 'distro/lhm/libreoffice-6-1+backports' - 3 commits - include/vcl sfx2/source vcl/inc vcl/source vcl/unx

Caolán McNamara (via logerrit) logerrit at kemper.freedesktop.org
Tue Sep 17 14:15:13 UTC 2019


 include/vcl/event.hxx        |    2 
 include/vcl/window.hxx       |    1 
 sfx2/source/view/frame2.cxx  |   34 +++++----
 vcl/inc/salframe.hxx         |    4 +
 vcl/source/window/dialog.cxx |   10 +-
 vcl/source/window/window.cxx |    5 +
 vcl/unx/gtk3/gtk3gtkinst.cxx |  149 ++++++++++++++++++++++++++++++++++++++++---
 7 files changed, 175 insertions(+), 30 deletions(-)

New commits:
commit 009a9ebb7cc0de49cd51b11995cf60d0ca45e7d3
Author:     Caolán McNamara <caolanm at redhat.com>
AuthorDate: Fri Jun 14 09:18:44 2019 +0100
Commit:     Michael Weghorn <m.weghorn at posteo.de>
CommitDate: Tue Sep 17 16:14:36 2019 +0200

    disable 'quit' menu entry when modal dialog waiting response
    
    Traditionally when a modal dialog is active, the quit menu entry of all
    LibreOffice toplevel frames, not just those which are themselves modal, is get
    disabled.
    
    This has come unstuck because its implemented by dialogs emitting
    MouseNotifyEvent::[END]EXECUTEDIALOG on its parent, and SfxFrameWindow_Impl
    listening for that event. But if the dialog parent is the toplevel parent of
    SfxFrameWindow_Impl then it doesn't get seen by the SfxFrameWindow_Impl child.
    
    Reviewed-on: https://gerrit.libreoffice.org/73975
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>
    (cherry picked from commit 252239ae30313142195b3da81aea45a89b2d6674)
    
     Conflicts:
            include/vcl/event.hxx
            include/vcl/window.hxx
            sfx2/source/view/frame2.cxx
            vcl/source/window/dialog.cxx
            vcl/source/window/window.cxx
    
    Change-Id: I0c4a5472d16d9169e68f6b0c230d039f1119489a
    Reviewed-on: https://gerrit.libreoffice.org/79040
    Reviewed-by: Michael Weghorn <m.weghorn at posteo.de>
    Tested-by: Michael Weghorn <m.weghorn at posteo.de>

diff --git a/include/vcl/event.hxx b/include/vcl/event.hxx
index 050e7199cc45..3a5122eb941a 100644
--- a/include/vcl/event.hxx
+++ b/include/vcl/event.hxx
@@ -290,8 +290,6 @@ enum class MouseNotifyEvent
     DESTROY          = 9,
     INPUTENABLE      = 10,
     INPUTDISABLE     = 11,
-    EXECUTEDIALOG    = 100,
-    ENDEXECUTEDIALOG = 101
 };
 
 class VCL_DLLPUBLIC NotifyEvent
diff --git a/include/vcl/window.hxx b/include/vcl/window.hxx
index 3a3ea99d2c0f..f0eaaff573f1 100644
--- a/include/vcl/window.hxx
+++ b/include/vcl/window.hxx
@@ -1605,6 +1605,7 @@ public:
     virtual bool IsChart() const { return false; }
 
     void SetHelpHdl(const Link<vcl::Window&, bool>& rLink);
+    void SetModalHierarchyHdl(const Link<bool, void>& rLink);
 };
 
 }
diff --git a/sfx2/source/view/frame2.cxx b/sfx2/source/view/frame2.cxx
index 6fc3cff26a7d..e003d9697358 100644
--- a/sfx2/source/view/frame2.cxx
+++ b/sfx2/source/view/frame2.cxx
@@ -58,9 +58,9 @@ using namespace ::com::sun::star::container;
 using namespace ::com::sun::star::beans;
 using ::com::sun::star::frame::XComponentLoader;
 
-
 class SfxFrameWindow_Impl : public vcl::Window
 {
+    DECL_LINK(ModalHierarchyHdl, bool, void);
 public:
     SfxFrame*           pFrame;
 
@@ -72,13 +72,21 @@ public:
     virtual bool        EventNotify( NotifyEvent& rEvt ) override;
     virtual void        Resize() override;
     virtual void        GetFocus() override;
+    virtual void        dispose() override;
     void                DoResize();
 };
 
-SfxFrameWindow_Impl::SfxFrameWindow_Impl( SfxFrame* pF, vcl::Window& i_rContainerWindow )
-        : Window( &i_rContainerWindow, WB_BORDER | WB_CLIPCHILDREN | WB_NODIALOGCONTROL | WB_3DLOOK )
-        , pFrame( pF )
+SfxFrameWindow_Impl::SfxFrameWindow_Impl(SfxFrame* pF, vcl::Window& i_rContainerWindow)
+    : Window(&i_rContainerWindow, WB_BORDER | WB_CLIPCHILDREN | WB_NODIALOGCONTROL | WB_3DLOOK)
+    , pFrame(pF)
+{
+    i_rContainerWindow.SetModalHierarchyHdl(LINK(this, SfxFrameWindow_Impl, ModalHierarchyHdl));
+}
+
+void SfxFrameWindow_Impl::dispose()
 {
+    GetParent()->SetModalHierarchyHdl(Link<bool, void>());
+    vcl::Window::dispose();
 }
 
 void SfxFrameWindow_Impl::DataChanged( const DataChangedEvent& rDCEvt )
@@ -116,20 +124,18 @@ bool SfxFrameWindow_Impl::EventNotify( NotifyEvent& rNEvt )
         if ( pView->GetViewShell()->KeyInput( *rNEvt.GetKeyEvent() ) )
             return true;
     }
-    else if ( rNEvt.GetType() == MouseNotifyEvent::EXECUTEDIALOG /*|| rNEvt.GetType() == MouseNotifyEvent::INPUTDISABLE*/ )
-    {
-        pView->SetModalMode( true );
-        return true;
-    }
-    else if ( rNEvt.GetType() == MouseNotifyEvent::ENDEXECUTEDIALOG /*|| rNEvt.GetType() == MouseNotifyEvent::INPUTENABLE*/ )
-    {
-        pView->SetModalMode( false );
-        return true;
-    }
 
     return Window::EventNotify( rNEvt );
 }
 
+IMPL_LINK(SfxFrameWindow_Impl, ModalHierarchyHdl, bool, bSetModal, void)
+{
+    SfxViewFrame* pView = pFrame->GetCurrentViewFrame();
+    if (!pView || !pView->GetObjectShell())
+        return;
+    pView->SetModalMode(bSetModal);
+}
+
 bool SfxFrameWindow_Impl::PreNotify( NotifyEvent& rNEvt )
 {
     MouseNotifyEvent nType = rNEvt.GetType();
diff --git a/vcl/inc/salframe.hxx b/vcl/inc/salframe.hxx
index e2662d415fc2..06d8b1835c03 100644
--- a/vcl/inc/salframe.hxx
+++ b/vcl/inc/salframe.hxx
@@ -108,6 +108,7 @@ private:
     // the VCL window corresponding to this frame
     VclPtr<vcl::Window>     m_pWindow;
     SALFRAMEPROC            m_pProc;
+    Link<bool, void>        m_aModalHierarchyHdl;
 protected:
     mutable std::unique_ptr<weld::Window> m_xFrameWeld;
 public:
@@ -273,6 +274,9 @@ public:
     // returns the instance set
     vcl::Window*            GetWindow() const { return m_pWindow; }
 
+    void SetModalHierarchyHdl(const Link<bool, void>& rLink) { m_aModalHierarchyHdl = rLink; }
+    void NotifyModalHierarchy(bool bModal) { m_aModalHierarchyHdl.Call(bModal); }
+
     // Call the callback set; this sometimes necessary for implementation classes
     // that should not know more than necessary about the SalFrame implementation
     // (e.g. input methods, printer update handlers).
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index a1d8cf1e6a6c..ef7dfe73c57e 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -913,11 +913,13 @@ bool Dialog::ImplStartExecuteModal()
         pSVData->maWinData.mpCaptureWin->ReleaseMouse();
     EnableInput();
 
+
     if ( GetParent() )
     {
-        NotifyEvent aNEvt( MouseNotifyEvent::EXECUTEDIALOG, this );
-        GetParent()->CompatNotify( aNEvt );
+        SalFrame* pFrame = GetParent()->ImplGetFrame();
+        pFrame->NotifyModalHierarchy(true);
     }
+
     mbInExecute = true;
     // no real modality in LibreOfficeKit
     if (!bKitActive)
@@ -1119,8 +1121,8 @@ void Dialog::EndDialog( long nResult )
     Hide();
     if ( GetParent() )
     {
-        NotifyEvent aNEvt( MouseNotifyEvent::ENDEXECUTEDIALOG, this );
-        GetParent()->CompatNotify( aNEvt );
+        SalFrame* pFrame = GetParent()->ImplGetFrame();
+        pFrame->NotifyModalHierarchy(false);
     }
 
     mpDialogImpl->mnResult = nResult;
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
index 3d7a5323227f..d15181288cf2 100644
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -1760,6 +1760,11 @@ void Window::ImplNewInputContext()
     pFocusWin->ImplGetFrame()->SetInputContext( &aNewContext );
 }
 
+void Window::SetModalHierarchyHdl(const Link<bool, void>& rLink)
+{
+    ImplGetFrame()->SetModalHierarchyHdl(rLink);
+}
+
 void Window::doLazyDelete()
 {
     SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(this);
commit 330cf24731919c049db1ad18697306dc046de65a
Author:     Caolán McNamara <caolanm at redhat.com>
AuthorDate: Sun Sep 9 14:09:37 2018 +0100
Commit:     Michael Weghorn <m.weghorn at posteo.de>
CommitDate: Tue Sep 17 16:14:33 2019 +0200

    silence bogus -Wmaybe-uninitialized
    
    Change-Id: I702b4818f05a606da30a643e13bfcd2c98ba412a
    Reviewed-on: https://gerrit.libreoffice.org/60215
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>
    (cherry picked from commit b829325fb407250849d9508ed32176b08006dd0a)
    Reviewed-on: https://gerrit.libreoffice.org/79039
    Reviewed-by: Michael Weghorn <m.weghorn at posteo.de>
    Tested-by: Michael Weghorn <m.weghorn at posteo.de>

diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index 4cb75e50f695..955705cdc72a 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -1813,7 +1813,7 @@ public:
     }
     virtual void set_mode(VclSizeGroupMode eVclMode) override
     {
-        GtkSizeGroupMode eGtkMode;
+        GtkSizeGroupMode eGtkMode(GTK_SIZE_GROUP_NONE);
         switch (eVclMode)
         {
             case VclSizeGroupMode::NONE:
commit 65c72516c9e3b915e123d6c715e86ef38ac46374
Author:     Caolán McNamara <caolanm at redhat.com>
AuthorDate: Tue Nov 27 10:18:52 2018 +0000
Commit:     Michael Weghorn <m.weghorn at posteo.de>
CommitDate: Tue Sep 17 16:14:27 2019 +0200

    enable hiding gtk dialogs without ending their dialog loop
    
    we need this to support reshowing dialog after an intermediate
    range selection dialog executes
    
    Reviewed-on: https://gerrit.libreoffice.org/64100
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>
    (cherry picked from commit 471d6c3653b8b8006db022c5d94af7503adfdc56)
    
     Conflicts:
            vcl/unx/gtk3/gtk3gtkinst.cxx
    
    Change-Id: Ib6575e5d852bd1d29cc1a791a5dc2c19949b67a0
    Reviewed-on: https://gerrit.libreoffice.org/79038
    Reviewed-by: Michael Weghorn <m.weghorn at posteo.de>
    Tested-by: Michael Weghorn <m.weghorn at posteo.de>

diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index 384f1d411e4d..4cb75e50f695 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -2029,10 +2029,117 @@ namespace
     }
 }
 
+struct DialogRunner
+{
+    GtkDialog *m_pDialog;
+    gint m_nResponseId;
+    GMainLoop *m_pLoop;
+    VclPtr<vcl::Window> m_xFrameWindow;
+
+    DialogRunner(GtkDialog* pDialog)
+       : m_pDialog(pDialog)
+       , m_nResponseId(GTK_RESPONSE_NONE)
+       , m_pLoop(nullptr)
+    {
+        GtkWindow* pParent = gtk_window_get_transient_for(GTK_WINDOW(m_pDialog));
+        GtkSalFrame* pFrame = GtkSalFrame::getFromWindow(pParent);
+        m_xFrameWindow = pFrame ? pFrame->GetWindow() : nullptr;
+    }
+
+    bool loop_is_running() const
+    {
+        return m_pLoop && g_main_loop_is_running(m_pLoop);
+    }
+
+    void loop_quit()
+    {
+        if (g_main_loop_is_running(m_pLoop))
+            g_main_loop_quit(m_pLoop);
+    }
+
+    static void signal_response(GtkDialog*, gint nResponseId, gpointer data)
+    {
+        DialogRunner* pThis = static_cast<DialogRunner*>(data);
+        pThis->m_nResponseId = nResponseId;
+        pThis->loop_quit();
+    }
+
+    static gboolean signal_delete(GtkDialog*, GdkEventAny*, gpointer data)
+    {
+        DialogRunner* pThis = static_cast<DialogRunner*>(data);
+        pThis->loop_quit();
+        return true; /* Do not destroy */
+    }
+
+    static void signal_destroy(GtkDialog*, gpointer data)
+    {
+        DialogRunner* pThis = static_cast<DialogRunner*>(data);
+        pThis->loop_quit();
+    }
+
+    void inc_modal_count()
+    {
+        if (m_xFrameWindow)
+            m_xFrameWindow->IncModalCount();
+    }
+
+    void dec_modal_count()
+    {
+        if (m_xFrameWindow)
+            m_xFrameWindow->DecModalCount();
+    }
+
+    // same as gtk_dialog_run except that unmap doesn't auto-respond
+    // so we can hide the dialog and restore it without a response getting
+    // triggered
+    gint run()
+    {
+        g_object_ref(m_pDialog);
+
+        inc_modal_count();
+
+        bool bWasModal = gtk_window_get_modal(GTK_WINDOW(m_pDialog));
+        if (!bWasModal)
+            gtk_window_set_modal(GTK_WINDOW(m_pDialog), true);
+
+        if (!gtk_widget_get_visible(GTK_WIDGET(m_pDialog)))
+            gtk_widget_show(GTK_WIDGET(m_pDialog));
+
+        gulong nSignalResponseId = g_signal_connect(m_pDialog, "response", G_CALLBACK(signal_response), this);
+        gulong nSignalDeleteId = g_signal_connect(m_pDialog, "delete-event", G_CALLBACK(signal_delete), this);
+        gulong nSignalDestroyId = g_signal_connect(m_pDialog, "destroy", G_CALLBACK(signal_destroy), this);
+
+        m_pLoop = g_main_loop_new(nullptr, false);
+        m_nResponseId = GTK_RESPONSE_NONE;
+
+        gdk_threads_leave();
+        g_main_loop_run(m_pLoop);
+        gdk_threads_enter();
+
+        g_main_loop_unref(m_pLoop);
+
+        m_pLoop = nullptr;
+
+        if (!bWasModal)
+            gtk_window_set_modal(GTK_WINDOW(m_pDialog), false);
+
+        g_signal_handler_disconnect(m_pDialog, nSignalResponseId);
+        g_signal_handler_disconnect(m_pDialog, nSignalDeleteId);
+        g_signal_handler_disconnect(m_pDialog, nSignalDestroyId);
+
+        dec_modal_count();
+
+        g_object_unref(m_pDialog);
+
+        return m_nResponseId;
+    }
+};
+
 class GtkInstanceDialog : public GtkInstanceWindow, public virtual weld::Dialog
 {
 private:
     GtkDialog* m_pDialog;
+    DialogRunner m_aDialogRun;
     std::shared_ptr<weld::DialogController> m_xDialogController;
     std::function<void(sal_Int32)> m_aFunc;
     gulong m_nCloseSignalId;
@@ -2082,10 +2189,12 @@ private:
         m_aFunc = nullptr;
         m_xDialogController.reset();
     }
+
 public:
     GtkInstanceDialog(GtkDialog* pDialog, bool bTakeOwnership)
         : GtkInstanceWindow(GTK_WINDOW(pDialog), bTakeOwnership)
         , m_pDialog(pDialog)
+        , m_aDialogRun(pDialog)
         , m_nCloseSignalId(g_signal_connect(m_pDialog, "close", G_CALLBACK(signalClose), this))
         , m_nResponseSignalId(0)
     {
@@ -2115,16 +2224,9 @@ public:
     {
         sort_native_button_order(GTK_BOX(gtk_dialog_get_action_area(m_pDialog)));
         int ret;
-        GtkWindow* pParent = gtk_window_get_transient_for(GTK_WINDOW(m_pDialog));
-        GtkSalFrame* pFrame = GtkSalFrame::getFromWindow(pParent);
-        vcl::Window* pFrameWindow = pFrame ? pFrame->GetWindow() : nullptr;
         while (true)
         {
-            if (pFrameWindow)
-                pFrameWindow->IncModalCount();
-            ret = gtk_dialog_run(m_pDialog);
-            if (pFrameWindow)
-                pFrameWindow->DecModalCount();
+            ret = m_aDialogRun.run();
             if (ret == GTK_RESPONSE_HELP)
             {
                 help();
@@ -2139,6 +2241,34 @@ public:
         return GtkToVcl(ret);
     }
 
+    virtual void hide() override
+    {
+        if (!gtk_widget_get_visible(m_pWidget))
+            return;
+        gtk_widget_hide(m_pWidget);
+        // if we hide the dialog while its running, then decrement the parent LibreOffice window
+        // modal count, we expect the dialog to restored while its running and match up with
+        // the inc_modal_count of show()
+        //
+        // This hide while running case is for the calc/chart dialogs which put
+        // up an extra range chooser dialog, hides the original, the user can
+        // select a range of cells and on completion the original dialog is
+        // restored
+        if (m_aDialogRun.loop_is_running())
+            m_aDialogRun.dec_modal_count();
+    }
+
+    virtual void show() override
+    {
+        if (gtk_widget_get_visible(m_pWidget))
+            return;
+        sort_native_button_order(GTK_BOX(gtk_dialog_get_action_area(m_pDialog)));
+        gtk_widget_show(m_pWidget);
+        // see hide comment
+        if (m_aDialogRun.loop_is_running())
+            m_aDialogRun.inc_modal_count();
+    }
+
     static int VclToGtk(int nResponse)
     {
         if (nResponse == RET_OK)
@@ -2359,7 +2489,6 @@ static void crippled_viewport_class_init(GtkViewportClass *klass)
     /* GObject signals */
     o_class->set_property = crippled_viewport_set_property;
     o_class->get_property = crippled_viewport_get_property;
-//    o_class->finalize = gtk_tree_view_finalize;
 
     /* Properties */
     g_object_class_override_property(o_class, PROP_HADJUSTMENT,    "hadjustment");


More information about the Libreoffice-commits mailing list