tdf#140225 call cancel before destroying menubar
a) in case there are some menus open cancel them before removing
their parent menubar
b) before a GtkSalMenu is deleted clear the action-group of its members
squash of...
Related: tdf#140225 ignore activate/deactivate of a disposed VclMenu
prep work for improved solution for tdf#140225
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/110699
Tested-by: Caolán McNamara <caolanm@redhat.com>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Related: tdf#140225 when clearing pItemList, keep SalMenu in sync
with their removal during menu teardown
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/110703
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Resolves: tdf#140225 remove action when item is removed from GtkSalMenu
and we have previously ensured that all items are removed by
Menu::dispose before GtkSalMenu dtor is called
Change-Id: I9ec59c52c72b8b58976a8ee41727ca7612ebf6b1
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/110564
Tested-by: Jenkins
Reviewed-by: Adolfo Jayme Barrientos <fitojb@ubuntu.com>
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
index eacfb86..7d4a346 100644
--- a/vcl/source/window/menu.cxx
+++ b/vcl/source/window/menu.cxx
@@ -213,7 +213,18 @@ void Menu::dispose()
bKilled = true;
pItemList->Clear();
// tdf#140225 when clearing pItemList, keep SalMenu in sync with
// their removal during menu teardown
for (size_t n = pItemList->size(); n;)
{
--n;
if (mpSalMenu)
mpSalMenu->RemoveItem(n);
pItemList->Remove(n);
}
assert(!pItemList->size());
mpLayoutData.reset();
// Native-support: destroy SalMenu
diff --git a/vcl/unx/gtk3/gtk3gtksalmenu.cxx b/vcl/unx/gtk3/gtk3gtksalmenu.cxx
index f78bbab..3ed2487 100644
--- a/vcl/unx/gtk3/gtk3gtksalmenu.cxx
+++ b/vcl/unx/gtk3/gtk3gtksalmenu.cxx
@@ -596,13 +596,15 @@ GtkSalMenu::~GtkSalMenu()
{
SolarMutexGuard aGuard;
// tdf#140225 we expect all items to be removed by Menu::dispose
// before this dtor is called
assert(maItems.empty());
DestroyMenuBarWidget();
if (mpMenuModel)
g_object_unref(mpMenuModel);
maItems.clear();
if (mpFrame)
mpFrame->SetMenu(nullptr);
}
@@ -630,6 +632,16 @@ void GtkSalMenu::InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos )
void GtkSalMenu::RemoveItem( unsigned nPos )
{
SolarMutexGuard aGuard;
// tdf#140225 clear associated action when the item is removed
if (mpActionGroup)
{
GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP(mpActionGroup);
gchar* pCommand = GetCommandForItem(maItems[nPos]);
g_lo_action_group_remove(pActionGroup, pCommand);
g_free(pCommand);
}
maItems.erase( maItems.begin() + nPos );
SetNeedsUpdate();
}
@@ -998,6 +1010,10 @@ void GtkSalMenu::DestroyMenuBarWidget()
{
if (mpMenuBarContainerWidget)
{
// tdf#140225 call cancel before destroying it in case there are some
// active menus popped open
gtk_menu_shell_cancel(GTK_MENU_SHELL(mpMenuBarWidget));
gtk_widget_destroy(mpMenuBarContainerWidget);
mpMenuBarContainerWidget = nullptr;
mpCloseButton = nullptr;
@@ -1345,8 +1361,10 @@ void GtkSalMenu::Activate(const gchar* pCommand)
{
MenuAndId aMenuAndId = decode_command(pCommand);
GtkSalMenu* pSalMenu = aMenuAndId.first;
GtkSalMenu* pTopLevel = pSalMenu->GetTopLevel();
Menu* pVclMenu = pSalMenu->GetMenu();
if (pVclMenu->isDisposed())
return;
GtkSalMenu* pTopLevel = pSalMenu->GetTopLevel();
Menu* pVclSubMenu = pVclMenu->GetPopupMenu(aMenuAndId.second);
GtkSalMenu* pSubMenu = pSalMenu->GetItemAtPos(pVclMenu->GetItemPos(aMenuAndId.second))->mpSubMenu;
@@ -1360,8 +1378,10 @@ void GtkSalMenu::Deactivate(const gchar* pCommand)
{
MenuAndId aMenuAndId = decode_command(pCommand);
GtkSalMenu* pSalMenu = aMenuAndId.first;
GtkSalMenu* pTopLevel = pSalMenu->GetTopLevel();
Menu* pVclMenu = pSalMenu->GetMenu();
if (pVclMenu->isDisposed())
return;
GtkSalMenu* pTopLevel = pSalMenu->GetTopLevel();
Menu* pVclSubMenu = pVclMenu->GetPopupMenu(aMenuAndId.second);
pTopLevel->GetMenu()->HandleMenuDeActivateEvent(pVclSubMenu);
}