parent
4b799c8e78
commit
300695674c
@ -0,0 +1,328 @@
|
|||||||
|
From 9e64526a0671b52cdb6b6ad567153402a85d21bf Mon Sep 17 00:00:00 2001
|
||||||
|
From: Maxim Monastirsky <momonasmon@gmail.com>
|
||||||
|
Date: Sun, 7 Feb 2016 17:53:40 +0200
|
||||||
|
Subject: [PATCH 1/8] tdf#97665 Let's hope that over activation isn't really
|
||||||
|
needed
|
||||||
|
|
||||||
|
- MenuBarManager::Activate has a check for duplicate activation,
|
||||||
|
which makes the second activation attempt fail. Removing this
|
||||||
|
check or deactivating after each activation will likely affect
|
||||||
|
performance even more, but on the other hand should solve
|
||||||
|
lp#1296715, which was the main reason of the over activation
|
||||||
|
in the first place. So let's activate only one menu at a time,
|
||||||
|
and do full activation only on the initial update.
|
||||||
|
|
||||||
|
- Unfortunately the HUD activation callback doesn't work, so
|
||||||
|
we still have to keep active status listener for all menu
|
||||||
|
items. (Which is BTW against the recommendation in
|
||||||
|
XPopupMenuController::updatePopupMenu IDL doc. Fortunately
|
||||||
|
the performance problem hardly noticeable on modern hw.)
|
||||||
|
|
||||||
|
Reviewed-on: https://gerrit.libreoffice.org/22369
|
||||||
|
Tested-by: Jenkins <ci@libreoffice.org>
|
||||||
|
Reviewed-by: Maxim Monastirsky <momonasmon@gmail.com>
|
||||||
|
(cherry picked from commit 2abdcfd641883f246fe78f2fbe38499c9382c059)
|
||||||
|
|
||||||
|
Change-Id: I96affa72412f3f38160fdca4b6efd20ca68d059f
|
||||||
|
---
|
||||||
|
framework/source/uielement/menubarmanager.cxx | 11 ++---
|
||||||
|
include/vcl/menu.hxx | 9 +---
|
||||||
|
vcl/inc/salmenu.hxx | 1 +
|
||||||
|
vcl/inc/unx/gtk/gtksalmenu.hxx | 4 +-
|
||||||
|
vcl/source/window/menu.cxx | 46 +++-----------------
|
||||||
|
vcl/unx/gtk/gloactiongroup.cxx | 2 +-
|
||||||
|
vcl/unx/gtk/gtkdata.cxx | 18 --------
|
||||||
|
vcl/unx/gtk/gtksalmenu.cxx | 62 +++++++--------------------
|
||||||
|
8 files changed, 31 insertions(+), 122 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/framework/source/uielement/menubarmanager.cxx b/framework/source/uielement/menubarmanager.cxx
|
||||||
|
index 6a368a9..8ce02c6 100644
|
||||||
|
--- a/framework/source/uielement/menubarmanager.cxx
|
||||||
|
+++ b/framework/source/uielement/menubarmanager.cxx
|
||||||
|
@@ -386,10 +386,6 @@ throw ( RuntimeException, std::exception )
|
||||||
|
OUString aFeatureURL = Event.FeatureURL.Complete;
|
||||||
|
|
||||||
|
SolarMutexGuard aSolarGuard;
|
||||||
|
- if ( m_bHasMenuBar )
|
||||||
|
- {
|
||||||
|
- vcl::MenuInvalidator::Invalidated();
|
||||||
|
- }
|
||||||
|
{
|
||||||
|
if ( m_bDisposed )
|
||||||
|
return;
|
||||||
|
@@ -488,6 +484,8 @@ throw ( RuntimeException, std::exception )
|
||||||
|
pMenuItemHandler->xMenuItemDispatch.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ if ( m_bHasMenuBar && !m_bActive )
|
||||||
|
+ m_pVCLMenu->UpdateNativeMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -895,9 +893,8 @@ IMPL_LINK_TYPED( MenuBarManager, Activate, Menu *, pMenu, bool )
|
||||||
|
if ( !bPopupMenu )
|
||||||
|
{
|
||||||
|
xMenuItemDispatch->addStatusListener( static_cast< XStatusListener* >( this ), aTargetURL );
|
||||||
|
- xMenuItemDispatch->removeStatusListener( static_cast< XStatusListener* >( this ), aTargetURL );
|
||||||
|
- if ( m_bHasMenuBar )
|
||||||
|
- xMenuItemDispatch->addStatusListener( static_cast< XStatusListener* >( this ), aTargetURL );
|
||||||
|
+ if ( !m_bHasMenuBar )
|
||||||
|
+ xMenuItemDispatch->removeStatusListener( static_cast< XStatusListener* >( this ), aTargetURL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( !bPopupMenu )
|
||||||
|
diff --git a/include/vcl/menu.hxx b/include/vcl/menu.hxx
|
||||||
|
index ade703b..0d6e16a 100644
|
||||||
|
--- a/include/vcl/menu.hxx
|
||||||
|
+++ b/include/vcl/menu.hxx
|
||||||
|
@@ -313,6 +313,8 @@ public:
|
||||||
|
void RemoveDisabledEntries( bool bCheckPopups = true, bool bRemoveEmptyPopups = false );
|
||||||
|
bool HasValidEntries( bool bCheckPopups = true );
|
||||||
|
|
||||||
|
+ void UpdateNativeMenu();
|
||||||
|
+
|
||||||
|
void SetItemText( sal_uInt16 nItemId, const OUString& rStr );
|
||||||
|
OUString GetItemText( sal_uInt16 nItemId ) const;
|
||||||
|
|
||||||
|
@@ -407,13 +409,6 @@ public:
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
-namespace vcl { namespace MenuInvalidator {
|
||||||
|
-
|
||||||
|
-VCL_DLLPUBLIC void AddMenuInvalidateListener(const Link<LinkParamNone*,void>&);
|
||||||
|
-VCL_DLLPUBLIC void Invalidated();
|
||||||
|
-
|
||||||
|
-}}
|
||||||
|
-
|
||||||
|
class VCL_DLLPUBLIC MenuBar : public Menu
|
||||||
|
{
|
||||||
|
Link<void*,void> maCloseHdl;
|
||||||
|
diff --git a/vcl/inc/salmenu.hxx b/vcl/inc/salmenu.hxx
|
||||||
|
index 287e19e..468994a 100644
|
||||||
|
--- a/vcl/inc/salmenu.hxx
|
||||||
|
+++ b/vcl/inc/salmenu.hxx
|
||||||
|
@@ -80,6 +80,7 @@ public:
|
||||||
|
virtual bool ShowNativePopupMenu(FloatingWindow * pWin, const Rectangle& rRect, FloatWinPopupFlags nFlags);
|
||||||
|
virtual bool AddMenuBarButton( const SalMenuButtonItem& ); // return false if not implemented or failure
|
||||||
|
virtual void RemoveMenuBarButton( sal_uInt16 nId );
|
||||||
|
+ virtual void Update() {}
|
||||||
|
|
||||||
|
// TODO: implement show/hide for the Win/Mac VCL native backends
|
||||||
|
virtual void ShowItem( unsigned nPos, bool bShow ) { EnableItem( nPos, bShow ); }
|
||||||
|
diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx
|
||||||
|
index 5d9c262..8df2c1d 100644
|
||||||
|
--- a/vcl/inc/unx/gtk/gtksalmenu.hxx
|
||||||
|
+++ b/vcl/inc/unx/gtk/gtksalmenu.hxx
|
||||||
|
@@ -96,11 +96,11 @@ public:
|
||||||
|
void NativeSetAccelerator( unsigned nSection, unsigned nItemPos, const vcl::KeyCode& rKeyCode, const OUString& rKeyName );
|
||||||
|
|
||||||
|
void DispatchCommand( gint itemId, const gchar* aCommand );
|
||||||
|
- void Activate();
|
||||||
|
+ void Activate( const gchar* aMenuCommand = nullptr );
|
||||||
|
void Deactivate( const gchar* aMenuCommand );
|
||||||
|
void Display( bool bVisible );
|
||||||
|
bool PrepUpdate();
|
||||||
|
- void Update(); // Update this menu only.
|
||||||
|
+ virtual void Update() override; // Update this menu only.
|
||||||
|
void UpdateFull(); // Update full menu hierarchy from this menu.
|
||||||
|
};
|
||||||
|
|
||||||
|
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
|
||||||
|
index 3a6e54c..4aa7d41 100644
|
||||||
|
--- a/vcl/source/window/menu.cxx
|
||||||
|
+++ b/vcl/source/window/menu.cxx
|
||||||
|
@@ -2314,6 +2314,12 @@ sal_uLong Menu::DeactivateMenuBar(sal_uLong nFocusId)
|
||||||
|
return nFocusId;
|
||||||
|
}
|
||||||
|
|
||||||
|
+void Menu::UpdateNativeMenu()
|
||||||
|
+{
|
||||||
|
+ if ( ImplGetSalMenu() )
|
||||||
|
+ ImplGetSalMenu()->Update();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void Menu::MenuBarKeyInput(const KeyEvent&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
@@ -3251,44 +3257,4 @@ ImplMenuDelData::~ImplMenuDelData()
|
||||||
|
const_cast< Menu* >( mpMenu )->ImplRemoveDel( *this );
|
||||||
|
}
|
||||||
|
|
||||||
|
-namespace vcl { namespace MenuInvalidator {
|
||||||
|
-
|
||||||
|
-struct MenuInvalidateListeners : public vcl::DeletionNotifier
|
||||||
|
-{
|
||||||
|
- std::vector<Link<LinkParamNone*,void>> m_aListeners;
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-static MenuInvalidateListeners* pMenuInvalidateListeners = nullptr;
|
||||||
|
-
|
||||||
|
-void AddMenuInvalidateListener(const Link<LinkParamNone*,void>& rLink)
|
||||||
|
-{
|
||||||
|
- if(!pMenuInvalidateListeners)
|
||||||
|
- pMenuInvalidateListeners = new MenuInvalidateListeners();
|
||||||
|
- // ensure uniqueness
|
||||||
|
- auto& rListeners = pMenuInvalidateListeners->m_aListeners;
|
||||||
|
- if (std::find(rListeners.begin(), rListeners.end(), rLink) == rListeners.end())
|
||||||
|
- rListeners.push_back( rLink );
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void Invalidated()
|
||||||
|
-{
|
||||||
|
- if(!pMenuInvalidateListeners)
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
- vcl::DeletionListener aDel( pMenuInvalidateListeners );
|
||||||
|
-
|
||||||
|
- auto& rYieldListeners = pMenuInvalidateListeners->m_aListeners;
|
||||||
|
- // Copy the list, because this can be destroyed when calling a Link...
|
||||||
|
- std::vector<Link<LinkParamNone*,void>> aCopy( rYieldListeners );
|
||||||
|
- for( Link<LinkParamNone*,void>& rLink : aCopy )
|
||||||
|
- {
|
||||||
|
- if (aDel.isDeleted()) break;
|
||||||
|
- // check this hasn't been removed in some re-enterancy scenario fdo#47368
|
||||||
|
- if( std::find(rYieldListeners.begin(), rYieldListeners.end(), rLink) != rYieldListeners.end() )
|
||||||
|
- rLink.Call( nullptr );
|
||||||
|
- }
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-} } // namespace vcl::MenuInvalidator
|
||||||
|
-
|
||||||
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||||
|
diff --git a/vcl/unx/gtk/gloactiongroup.cxx b/vcl/unx/gtk/gloactiongroup.cxx
|
||||||
|
index 8385388..e710809 100644
|
||||||
|
--- a/vcl/unx/gtk/gloactiongroup.cxx
|
||||||
|
+++ b/vcl/unx/gtk/gloactiongroup.cxx
|
||||||
|
@@ -201,7 +201,7 @@ g_lo_action_group_perform_submenu_action (GLOActionGroup *group,
|
||||||
|
SAL_INFO("vcl.unity", "g_lo_action_group_perform_submenu_action on " << group << " to " << bState);
|
||||||
|
|
||||||
|
if (bState)
|
||||||
|
- pSalMenu->Activate();
|
||||||
|
+ pSalMenu->Activate (action_name);
|
||||||
|
else
|
||||||
|
pSalMenu->Deactivate (action_name);
|
||||||
|
}
|
||||||
|
diff --git a/vcl/unx/gtk/gtkdata.cxx b/vcl/unx/gtk/gtkdata.cxx
|
||||||
|
index b5c64e0..9ea6dc9 100644
|
||||||
|
--- a/vcl/unx/gtk/gtkdata.cxx
|
||||||
|
+++ b/vcl/unx/gtk/gtkdata.cxx
|
||||||
|
@@ -1030,22 +1030,4 @@ void GtkSalDisplay::deregisterFrame( SalFrame* pFrame )
|
||||||
|
SalGenericDisplay::deregisterFrame( pFrame );
|
||||||
|
}
|
||||||
|
|
||||||
|
-#if GTK_CHECK_VERSION(3,0,0)
|
||||||
|
-void GtkSalDisplay::RefreshMenusUnity()
|
||||||
|
-{
|
||||||
|
-#ifdef ENABLE_GMENU_INTEGRATION
|
||||||
|
- for(auto pSalFrame : m_aFrames) {
|
||||||
|
- auto pGtkSalFrame( static_cast<GtkSalFrame*>(pSalFrame));
|
||||||
|
- GtkSalMenu* pSalMenu = static_cast<GtkSalMenu*>(pGtkSalFrame->GetMenu());
|
||||||
|
- if(pSalMenu) {
|
||||||
|
- pSalMenu->Activate();
|
||||||
|
- pSalMenu->UpdateFull();
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-#else
|
||||||
|
- (void) this;
|
||||||
|
-#endif
|
||||||
|
-}
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||||
|
diff --git a/vcl/unx/gtk/gtksalmenu.cxx b/vcl/unx/gtk/gtksalmenu.cxx
|
||||||
|
index a0cc977..fd29a25 100644
|
||||||
|
--- a/vcl/unx/gtk/gtksalmenu.cxx
|
||||||
|
+++ b/vcl/unx/gtk/gtksalmenu.cxx
|
||||||
|
@@ -372,54 +372,9 @@ void GtkSalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsig
|
||||||
|
pItem->mpSubMenu = pGtkSubMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static bool bInvalidMenus = false;
|
||||||
|
-static gboolean RefreshMenusUnity(gpointer)
|
||||||
|
-{
|
||||||
|
- SolarMutexGuard g;
|
||||||
|
-#if GTK_CHECK_VERSION(3,0,0)
|
||||||
|
- GetGtkSalData()->GetGtkDisplay()->RefreshMenusUnity();
|
||||||
|
-#else
|
||||||
|
- SalDisplay* pSalDisplay = vcl_sal::getSalDisplay(GetGenericData());
|
||||||
|
- std::list< SalFrame* >::const_iterator pSalFrame = pSalDisplay->getFrames().begin();
|
||||||
|
- std::list< SalFrame* >::const_iterator pEndSalFrame = pSalDisplay->getFrames().end();
|
||||||
|
- for(; pSalFrame != pEndSalFrame; ++pSalFrame) {
|
||||||
|
- const GtkSalFrame* pGtkSalFrame = static_cast< const GtkSalFrame* >( *pSalFrame );
|
||||||
|
- GtkSalFrame* pFrameNonConst = const_cast<GtkSalFrame*>(pGtkSalFrame);
|
||||||
|
- GtkSalMenu* pSalMenu = static_cast<GtkSalMenu*>(pFrameNonConst->GetMenu());
|
||||||
|
- if(pSalMenu) {
|
||||||
|
- pSalMenu->Activate();
|
||||||
|
- pSalMenu->UpdateFull();
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-#endif
|
||||||
|
- bInvalidMenus = false;
|
||||||
|
- return FALSE;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void RefreshMenusUnity(void*, LinkParamNone*)
|
||||||
|
-{
|
||||||
|
- if(!bInvalidMenus) {
|
||||||
|
- g_timeout_add(10, &RefreshMenusUnity, nullptr);
|
||||||
|
- bInvalidMenus = true;
|
||||||
|
- }
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static Link<LinkParamNone*,void>* getRefreshLinkInstance()
|
||||||
|
-{
|
||||||
|
- static Link<LinkParamNone*,void>* pLink = nullptr;
|
||||||
|
- if(!pLink) {
|
||||||
|
- pLink = new Link<LinkParamNone*,void>(nullptr, &RefreshMenusUnity);
|
||||||
|
- }
|
||||||
|
- return pLink;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
void GtkSalMenu::SetFrame( const SalFrame* pFrame )
|
||||||
|
{
|
||||||
|
SolarMutexGuard aGuard;
|
||||||
|
- {
|
||||||
|
- vcl::MenuInvalidator::AddMenuInvalidateListener(*getRefreshLinkInstance());
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
assert(mbMenuBar);
|
||||||
|
SAL_INFO("vcl.unity", "GtkSalMenu set to frame");
|
||||||
|
mpFrame = static_cast< const GtkSalFrame* >( pFrame );
|
||||||
|
@@ -674,6 +629,7 @@ void GtkSalMenu::DispatchCommand( gint itemId, const gchar *aCommand )
|
||||||
|
void GtkSalMenu::ActivateAllSubmenus(MenuBar* pMenuBar)
|
||||||
|
{
|
||||||
|
pMenuBar->HandleMenuActivateEvent(mpVCLMenu);
|
||||||
|
+ pMenuBar->HandleMenuDeActivateEvent(mpVCLMenu);
|
||||||
|
for ( size_t nPos = 0; nPos < maItems.size(); nPos++ )
|
||||||
|
{
|
||||||
|
GtkSalMenuItem *pSalItem = maItems[ nPos ];
|
||||||
|
@@ -685,11 +641,23 @@ void GtkSalMenu::ActivateAllSubmenus(MenuBar* pMenuBar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-void GtkSalMenu::Activate()
|
||||||
|
+void GtkSalMenu::Activate( const gchar* aMenuCommand )
|
||||||
|
{
|
||||||
|
if ( !mbMenuBar )
|
||||||
|
return;
|
||||||
|
- ActivateAllSubmenus(static_cast<MenuBar*>(mpVCLMenu));
|
||||||
|
+
|
||||||
|
+ if ( !aMenuCommand ) {
|
||||||
|
+ ActivateAllSubmenus( static_cast< MenuBar* >( mpVCLMenu ) );
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ GtkSalMenu* pSalSubMenu = GetMenuForItemCommand( const_cast<gchar*>(aMenuCommand), TRUE );
|
||||||
|
+
|
||||||
|
+ if ( pSalSubMenu != nullptr ) {
|
||||||
|
+ MenuBar* pMenuBar = static_cast< MenuBar* >( mpVCLMenu );
|
||||||
|
+ pMenuBar->HandleMenuActivateEvent( pSalSubMenu->mpVCLMenu );
|
||||||
|
+ pSalSubMenu->Update();
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
void GtkSalMenu::Deactivate( const gchar* aMenuCommand )
|
||||||
|
--
|
||||||
|
2.7.1
|
||||||
|
|
@ -0,0 +1,172 @@
|
|||||||
|
From 684f2191c0010aaa5c802a306bef209660df0968 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com>
|
||||||
|
Date: Mon, 22 Feb 2016 20:57:52 +0000
|
||||||
|
Subject: [PATCH 2/8] gtk3: some changes towards enabling native gtk3 popup
|
||||||
|
menus
|
||||||
|
|
||||||
|
these menubar things can be menu things and can then do
|
||||||
|
away with the casting, no logic changes intended
|
||||||
|
|
||||||
|
Change-Id: Ibb1b5354d5e1483327f172d6890e134f1e4b9ee4
|
||||||
|
(cherry picked from commit c13a0b1f9e76584a4ffaea0ba754c8f9a01793d8)
|
||||||
|
---
|
||||||
|
include/vcl/menu.hxx | 8 ++++----
|
||||||
|
vcl/inc/unx/gtk/gtksalmenu.hxx | 4 ++--
|
||||||
|
vcl/source/window/menu.cxx | 15 +++++++--------
|
||||||
|
vcl/unx/gtk/gtksalmenu.cxx | 13 +++++--------
|
||||||
|
4 files changed, 18 insertions(+), 22 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/include/vcl/menu.hxx b/include/vcl/menu.hxx
|
||||||
|
index 0d6e16a..1dbd85e 100644
|
||||||
|
--- a/include/vcl/menu.hxx
|
||||||
|
+++ b/include/vcl/menu.hxx
|
||||||
|
@@ -406,8 +406,11 @@ public:
|
||||||
|
|
||||||
|
void HighlightItem( sal_uInt16 nItemPos );
|
||||||
|
void DeHighlight() { HighlightItem( 0xFFFF ); } // MENUITEMPOS_INVALID
|
||||||
|
-};
|
||||||
|
|
||||||
|
+ bool HandleMenuCommandEvent(Menu *pMenu, sal_uInt16 nEventId) const;
|
||||||
|
+ bool HandleMenuActivateEvent(Menu *pMenu) const;
|
||||||
|
+ bool HandleMenuDeActivateEvent(Menu *pMenu) const;
|
||||||
|
+};
|
||||||
|
|
||||||
|
class VCL_DLLPUBLIC MenuBar : public Menu
|
||||||
|
{
|
||||||
|
@@ -458,10 +461,7 @@ public:
|
||||||
|
void ShowButtons( bool bClose, bool bFloat, bool bHide );
|
||||||
|
|
||||||
|
virtual void SelectItem(sal_uInt16 nId) override;
|
||||||
|
- bool HandleMenuActivateEvent(Menu *pMenu) const;
|
||||||
|
- bool HandleMenuDeActivateEvent(Menu *pMenu) const;
|
||||||
|
bool HandleMenuHighlightEvent(Menu *pMenu, sal_uInt16 nEventId) const;
|
||||||
|
- bool HandleMenuCommandEvent(Menu *pMenu, sal_uInt16 nEventId) const;
|
||||||
|
bool HandleMenuButtonEvent(Menu *pMenu, sal_uInt16 nEventId);
|
||||||
|
|
||||||
|
void SetCloseButtonClickHdl( const Link<void*,void>& rLink ) { maCloseHdl = rLink; }
|
||||||
|
diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx
|
||||||
|
index 8df2c1d..1d58b7a 100644
|
||||||
|
--- a/vcl/inc/unx/gtk/gtksalmenu.hxx
|
||||||
|
+++ b/vcl/inc/unx/gtk/gtksalmenu.hxx
|
||||||
|
@@ -42,7 +42,7 @@ class GtkSalMenu : public SalMenu
|
||||||
|
private:
|
||||||
|
std::vector< GtkSalMenuItem* > maItems;
|
||||||
|
|
||||||
|
- bool mbMenuBar;
|
||||||
|
+ bool mbMenuBar;
|
||||||
|
Menu* mpVCLMenu;
|
||||||
|
GtkSalMenu* mpParentSalMenu;
|
||||||
|
const GtkSalFrame* mpFrame;
|
||||||
|
@@ -53,7 +53,7 @@ private:
|
||||||
|
|
||||||
|
GtkSalMenu* GetMenuForItemCommand( gchar* aCommand, gboolean bGetSubmenu );
|
||||||
|
void ImplUpdate( gboolean bRecurse );
|
||||||
|
- void ActivateAllSubmenus(MenuBar* pMenuBar);
|
||||||
|
+ void ActivateAllSubmenus(Menu* pMenuBar);
|
||||||
|
|
||||||
|
public:
|
||||||
|
GtkSalMenu( bool bMenuBar );
|
||||||
|
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
|
||||||
|
index 4aa7d41..999085e 100644
|
||||||
|
--- a/vcl/source/window/menu.cxx
|
||||||
|
+++ b/vcl/source/window/menu.cxx
|
||||||
|
@@ -2679,14 +2679,13 @@ void MenuBar::SelectItem(sal_uInt16 nId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// handler for native menu selection and command events
|
||||||
|
-
|
||||||
|
-bool MenuBar::HandleMenuActivateEvent( Menu *pMenu ) const
|
||||||
|
+bool Menu::HandleMenuActivateEvent( Menu *pMenu ) const
|
||||||
|
{
|
||||||
|
if( pMenu )
|
||||||
|
{
|
||||||
|
ImplMenuDelData aDelData( this );
|
||||||
|
|
||||||
|
- pMenu->pStartedFrom = const_cast<MenuBar*>(this);
|
||||||
|
+ pMenu->pStartedFrom = const_cast<Menu*>(this);
|
||||||
|
pMenu->bInCallback = true;
|
||||||
|
pMenu->Activate();
|
||||||
|
|
||||||
|
@@ -2696,13 +2695,13 @@ bool MenuBar::HandleMenuActivateEvent( Menu *pMenu ) const
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool MenuBar::HandleMenuDeActivateEvent( Menu *pMenu ) const
|
||||||
|
+bool Menu::HandleMenuDeActivateEvent( Menu *pMenu ) const
|
||||||
|
{
|
||||||
|
if( pMenu )
|
||||||
|
{
|
||||||
|
ImplMenuDelData aDelData( this );
|
||||||
|
|
||||||
|
- pMenu->pStartedFrom = const_cast<MenuBar*>(this);
|
||||||
|
+ pMenu->pStartedFrom = const_cast<Menu*>(this);
|
||||||
|
pMenu->bInCallback = true;
|
||||||
|
pMenu->Deactivate();
|
||||||
|
if( !aDelData.isDeleted() )
|
||||||
|
@@ -2735,14 +2734,14 @@ bool MenuBar::HandleMenuHighlightEvent( Menu *pMenu, sal_uInt16 nHighlightEventI
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool MenuBar::HandleMenuCommandEvent( Menu *pMenu, sal_uInt16 nCommandEventId ) const
|
||||||
|
+bool Menu::HandleMenuCommandEvent( Menu *pMenu, sal_uInt16 nCommandEventId ) const
|
||||||
|
{
|
||||||
|
if( !pMenu )
|
||||||
|
- pMenu = const_cast<MenuBar*>(this)->ImplFindMenu(nCommandEventId);
|
||||||
|
+ pMenu = const_cast<Menu*>(this)->ImplFindMenu(nCommandEventId);
|
||||||
|
if( pMenu )
|
||||||
|
{
|
||||||
|
pMenu->nSelectedId = nCommandEventId;
|
||||||
|
- pMenu->pStartedFrom = const_cast<MenuBar*>(this);
|
||||||
|
+ pMenu->pStartedFrom = const_cast<Menu*>(this);
|
||||||
|
pMenu->ImplSelect();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
diff --git a/vcl/unx/gtk/gtksalmenu.cxx b/vcl/unx/gtk/gtksalmenu.cxx
|
||||||
|
index fd29a25..6887ade 100644
|
||||||
|
--- a/vcl/unx/gtk/gtksalmenu.cxx
|
||||||
|
+++ b/vcl/unx/gtk/gtksalmenu.cxx
|
||||||
|
@@ -622,11 +622,10 @@ void GtkSalMenu::DispatchCommand( gint itemId, const gchar *aCommand )
|
||||||
|
GtkSalMenu* pSalSubMenu = GetMenuForItemCommand( const_cast<gchar*>(aCommand), FALSE );
|
||||||
|
Menu* pSubMenu = ( pSalSubMenu != nullptr ) ? pSalSubMenu->GetMenu() : nullptr;
|
||||||
|
|
||||||
|
- MenuBar* pMenuBar = static_cast< MenuBar* >( mpVCLMenu );
|
||||||
|
- pMenuBar->HandleMenuCommandEvent( pSubMenu, itemId );
|
||||||
|
+ mpVCLMenu->HandleMenuCommandEvent( pSubMenu, itemId );
|
||||||
|
}
|
||||||
|
|
||||||
|
-void GtkSalMenu::ActivateAllSubmenus(MenuBar* pMenuBar)
|
||||||
|
+void GtkSalMenu::ActivateAllSubmenus(Menu* pMenuBar)
|
||||||
|
{
|
||||||
|
pMenuBar->HandleMenuActivateEvent(mpVCLMenu);
|
||||||
|
pMenuBar->HandleMenuDeActivateEvent(mpVCLMenu);
|
||||||
|
@@ -647,15 +646,14 @@ void GtkSalMenu::Activate( const gchar* aMenuCommand )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( !aMenuCommand ) {
|
||||||
|
- ActivateAllSubmenus( static_cast< MenuBar* >( mpVCLMenu ) );
|
||||||
|
+ ActivateAllSubmenus(mpVCLMenu);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkSalMenu* pSalSubMenu = GetMenuForItemCommand( const_cast<gchar*>(aMenuCommand), TRUE );
|
||||||
|
|
||||||
|
if ( pSalSubMenu != nullptr ) {
|
||||||
|
- MenuBar* pMenuBar = static_cast< MenuBar* >( mpVCLMenu );
|
||||||
|
- pMenuBar->HandleMenuActivateEvent( pSalSubMenu->mpVCLMenu );
|
||||||
|
+ mpVCLMenu->HandleMenuActivateEvent( pSalSubMenu->mpVCLMenu );
|
||||||
|
pSalSubMenu->Update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -668,8 +666,7 @@ void GtkSalMenu::Deactivate( const gchar* aMenuCommand )
|
||||||
|
GtkSalMenu* pSalSubMenu = GetMenuForItemCommand( const_cast<gchar*>(aMenuCommand), TRUE );
|
||||||
|
|
||||||
|
if ( pSalSubMenu != nullptr ) {
|
||||||
|
- MenuBar* pMenuBar = static_cast< MenuBar* >( mpVCLMenu );
|
||||||
|
- pMenuBar->HandleMenuDeActivateEvent( pSalSubMenu->mpVCLMenu );
|
||||||
|
+ mpVCLMenu->HandleMenuDeActivateEvent( pSalSubMenu->mpVCLMenu );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.7.1
|
||||||
|
|
@ -0,0 +1,81 @@
|
|||||||
|
From 67d1d0061c1cf5bb8aba0de75776435150c8559e Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com>
|
||||||
|
Date: Tue, 23 Feb 2016 14:42:29 +0000
|
||||||
|
Subject: [PATCH 3/8] gtk3: vcl popups flush any unexecuted Select events on
|
||||||
|
popdown
|
||||||
|
|
||||||
|
so if the gtksalmenu integration wants to drive popups by setting a selection
|
||||||
|
on the vcl popup, then the same flush is needed after ShowNativePopupMenu
|
||||||
|
|
||||||
|
(cherry picked from commit 3cb62eacae001df546c2a8f39ae4d37c33791d0b)
|
||||||
|
|
||||||
|
Change-Id: I59be60de5742d1e382cabefcbf0d8cdd5fc30b00
|
||||||
|
---
|
||||||
|
include/vcl/menu.hxx | 1 +
|
||||||
|
vcl/source/window/menu.cxx | 24 +++++++++++++++---------
|
||||||
|
2 files changed, 16 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/include/vcl/menu.hxx b/include/vcl/menu.hxx
|
||||||
|
index 1dbd85e..f10141b 100644
|
||||||
|
--- a/include/vcl/menu.hxx
|
||||||
|
+++ b/include/vcl/menu.hxx
|
||||||
|
@@ -515,6 +515,7 @@ private:
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SAL_DLLPRIVATE sal_uInt16 ImplExecute( vcl::Window* pWindow, const Rectangle& rRect, FloatWinPopupFlags nPopupFlags, Menu* pStaredFrom, bool bPreSelectFirst );
|
||||||
|
+ SAL_DLLPRIVATE void ImplFlushPendingSelect();
|
||||||
|
SAL_DLLPRIVATE long ImplCalcHeight( sal_uInt16 nEntries ) const;
|
||||||
|
SAL_DLLPRIVATE sal_uInt16 ImplCalcVisEntries( long nMaxHeight, sal_uInt16 nStartEntry = 0, sal_uInt16* pLastVisible = nullptr ) const;
|
||||||
|
|
||||||
|
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
|
||||||
|
index 999085e..b753fac 100644
|
||||||
|
--- a/vcl/source/window/menu.cxx
|
||||||
|
+++ b/vcl/source/window/menu.cxx
|
||||||
|
@@ -2933,6 +2933,19 @@ sal_uInt16 PopupMenu::Execute( vcl::Window* pExecWindow, const Rectangle& rRect,
|
||||||
|
return ImplExecute( pExecWindow, rRect, nPopupModeFlags, nullptr, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
+void PopupMenu::ImplFlushPendingSelect()
|
||||||
|
+{
|
||||||
|
+ // is there still Select?
|
||||||
|
+ Menu* pSelect = ImplFindSelectMenu();
|
||||||
|
+ if (pSelect)
|
||||||
|
+ {
|
||||||
|
+ // Select should be called prior to leaving execute in a popup menu!
|
||||||
|
+ Application::RemoveUserEvent( pSelect->nEventId );
|
||||||
|
+ pSelect->nEventId = nullptr;
|
||||||
|
+ pSelect->Select();
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
sal_uInt16 PopupMenu::ImplExecute( vcl::Window* pW, const Rectangle& rRect, FloatWinPopupFlags nPopupModeFlags, Menu* pSFrom, bool bPreSelectFirst )
|
||||||
|
{
|
||||||
|
if ( !pSFrom && ( PopupMenu::IsInExecute() || !GetItemCount() ) )
|
||||||
|
@@ -3097,6 +3110,7 @@ sal_uInt16 PopupMenu::ImplExecute( vcl::Window* pW, const Rectangle& rRect, Floa
|
||||||
|
SalMenu* pMenu = ImplGetSalMenu();
|
||||||
|
if( pMenu && bRealExecute && pMenu->ShowNativePopupMenu( pWin, aRect, nPopupModeFlags | FloatWinPopupFlags::GrabFocus ) )
|
||||||
|
{
|
||||||
|
+ ImplFlushPendingSelect();
|
||||||
|
pWin->StopExecute();
|
||||||
|
pWin->doShutdown();
|
||||||
|
pWindow->doLazyDelete();
|
||||||
|
@@ -3180,15 +3194,7 @@ sal_uInt16 PopupMenu::ImplExecute( vcl::Window* pW, const Rectangle& rRect, Floa
|
||||||
|
pWindow->doLazyDelete();
|
||||||
|
pWindow = nullptr;
|
||||||
|
|
||||||
|
- // is there still Select?
|
||||||
|
- Menu* pSelect = ImplFindSelectMenu();
|
||||||
|
- if ( pSelect )
|
||||||
|
- {
|
||||||
|
- // Select should be called prior to leaving execute in a popup menu!
|
||||||
|
- Application::RemoveUserEvent( pSelect->nEventId );
|
||||||
|
- pSelect->nEventId = nullptr;
|
||||||
|
- pSelect->Select();
|
||||||
|
- }
|
||||||
|
+ ImplFlushPendingSelect();
|
||||||
|
}
|
||||||
|
|
||||||
|
return bRealExecute ? nSelectedId : 0;
|
||||||
|
--
|
||||||
|
2.7.1
|
||||||
|
|
@ -0,0 +1,77 @@
|
|||||||
|
From 1d40ccd2f55173f954e596ce59bc4307eceae453 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com>
|
||||||
|
Date: Wed, 24 Feb 2016 10:40:10 +0000
|
||||||
|
Subject: [PATCH 4/8] gtk3: replace old action if same command is added
|
||||||
|
|
||||||
|
i.e. originally we preferred the old action, now
|
||||||
|
prefer the new action because e.g. wrap items in
|
||||||
|
writer only contain their "checkable" state on
|
||||||
|
their update
|
||||||
|
|
||||||
|
Change-Id: I6a6ce94126253396cc273834a7e8a4fb0a56921d
|
||||||
|
(cherry picked from commit 36bddcbaa2d1673c1331c788eae9534aca2c5ec3)
|
||||||
|
---
|
||||||
|
vcl/unx/gtk/gtksalmenu.cxx | 45 +++++++++++++++++++++++----------------------
|
||||||
|
1 file changed, 23 insertions(+), 22 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/vcl/unx/gtk/gtksalmenu.cxx b/vcl/unx/gtk/gtksalmenu.cxx
|
||||||
|
index 6887ade..a9a0932 100644
|
||||||
|
--- a/vcl/unx/gtk/gtksalmenu.cxx
|
||||||
|
+++ b/vcl/unx/gtk/gtksalmenu.cxx
|
||||||
|
@@ -530,30 +530,31 @@ void GtkSalMenu::NativeSetItemCommand( unsigned nSection,
|
||||||
|
|
||||||
|
GVariant *pTarget = nullptr;
|
||||||
|
|
||||||
|
- if ( g_action_group_has_action( mpActionGroup, aCommand ) == FALSE ) {
|
||||||
|
- if ( ( nBits & MenuItemBits::CHECKABLE ) || bIsSubmenu )
|
||||||
|
- {
|
||||||
|
- // Item is a checkmark button.
|
||||||
|
- GVariantType* pStateType = g_variant_type_new( reinterpret_cast<gchar const *>(G_VARIANT_TYPE_BOOLEAN) );
|
||||||
|
- GVariant* pState = g_variant_new_boolean( bChecked );
|
||||||
|
+ if (g_action_group_has_action(mpActionGroup, aCommand))
|
||||||
|
+ g_lo_action_group_remove(pActionGroup, aCommand);
|
||||||
|
|
||||||
|
- g_lo_action_group_insert_stateful( pActionGroup, aCommand, nId, bIsSubmenu, nullptr, pStateType, nullptr, pState );
|
||||||
|
- }
|
||||||
|
- else if ( nBits & MenuItemBits::RADIOCHECK )
|
||||||
|
- {
|
||||||
|
- // Item is a radio button.
|
||||||
|
- GVariantType* pParameterType = g_variant_type_new( reinterpret_cast<gchar const *>(G_VARIANT_TYPE_STRING) );
|
||||||
|
- GVariantType* pStateType = g_variant_type_new( reinterpret_cast<gchar const *>(G_VARIANT_TYPE_STRING) );
|
||||||
|
- GVariant* pState = g_variant_new_string( "" );
|
||||||
|
- pTarget = g_variant_new_string( aCommand );
|
||||||
|
+ if ( ( nBits & MenuItemBits::CHECKABLE ) || bIsSubmenu )
|
||||||
|
+ {
|
||||||
|
+ // Item is a checkmark button.
|
||||||
|
+ GVariantType* pStateType = g_variant_type_new( reinterpret_cast<gchar const *>(G_VARIANT_TYPE_BOOLEAN) );
|
||||||
|
+ GVariant* pState = g_variant_new_boolean( bChecked );
|
||||||
|
|
||||||
|
- g_lo_action_group_insert_stateful( pActionGroup, aCommand, nId, FALSE, pParameterType, pStateType, nullptr, pState );
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- // Item is not special, so insert a stateless action.
|
||||||
|
- g_lo_action_group_insert( pActionGroup, aCommand, nId, FALSE );
|
||||||
|
- }
|
||||||
|
+ g_lo_action_group_insert_stateful( pActionGroup, aCommand, nId, bIsSubmenu, nullptr, pStateType, nullptr, pState );
|
||||||
|
+ }
|
||||||
|
+ else if ( nBits & MenuItemBits::RADIOCHECK )
|
||||||
|
+ {
|
||||||
|
+ // Item is a radio button.
|
||||||
|
+ GVariantType* pParameterType = g_variant_type_new( reinterpret_cast<gchar const *>(G_VARIANT_TYPE_STRING) );
|
||||||
|
+ GVariantType* pStateType = g_variant_type_new( reinterpret_cast<gchar const *>(G_VARIANT_TYPE_STRING) );
|
||||||
|
+ GVariant* pState = g_variant_new_string( "" );
|
||||||
|
+ pTarget = g_variant_new_string( aCommand );
|
||||||
|
+
|
||||||
|
+ g_lo_action_group_insert_stateful( pActionGroup, aCommand, nId, FALSE, pParameterType, pStateType, nullptr, pState );
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ // Item is not special, so insert a stateless action.
|
||||||
|
+ g_lo_action_group_insert( pActionGroup, aCommand, nId, FALSE );
|
||||||
|
}
|
||||||
|
|
||||||
|
GLOMenu* pMenu = G_LO_MENU( mpMenuModel );
|
||||||
|
--
|
||||||
|
2.7.1
|
||||||
|
|
@ -0,0 +1,32 @@
|
|||||||
|
From 33d05b5ca87d1ddb76fef373a92833d07c00cb15 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com>
|
||||||
|
Date: Wed, 24 Feb 2016 12:19:49 +0000
|
||||||
|
Subject: [PATCH 5/8] gtk3: handle items without commands
|
||||||
|
|
||||||
|
e.g. the draw/impress context menus. Handle these like
|
||||||
|
MenuManager::Activate does
|
||||||
|
|
||||||
|
Change-Id: I02a0e377a2d3a57ac7ac9239aaa75dbb856489d2
|
||||||
|
(cherry picked from commit b8ee342576b707dbffe877f5c225b640ee65276d)
|
||||||
|
---
|
||||||
|
vcl/unx/gtk/gtksalmenu.cxx | 4 +++-
|
||||||
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/vcl/unx/gtk/gtksalmenu.cxx b/vcl/unx/gtk/gtksalmenu.cxx
|
||||||
|
index a9a0932..346e42d 100644
|
||||||
|
--- a/vcl/unx/gtk/gtksalmenu.cxx
|
||||||
|
+++ b/vcl/unx/gtk/gtksalmenu.cxx
|
||||||
|
@@ -52,7 +52,9 @@ static gchar* GetCommandForItem( GtkSalMenuItem* pSalMenuItem, gchar* aCurrentCo
|
||||||
|
if ( !pMenu )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
- OUString aMenuCommand = pMenu->GetItemCommand( nId );
|
||||||
|
+ OUString aMenuCommand = pMenu->GetItemCommand(nId);
|
||||||
|
+ if (aMenuCommand.isEmpty())
|
||||||
|
+ aMenuCommand = "slot:" + OUString::number(nId);
|
||||||
|
gchar* aCommandStr = g_strdup( OUStringToOString( aMenuCommand, RTL_TEXTENCODING_UTF8 ).getStr() );
|
||||||
|
aCommand = g_strdup( aCommandStr );
|
||||||
|
|
||||||
|
--
|
||||||
|
2.7.1
|
||||||
|
|
@ -0,0 +1,64 @@
|
|||||||
|
From 7dc5977edb7e34aed68aeb68846dee227f1a32de Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com>
|
||||||
|
Date: Wed, 24 Feb 2016 13:02:40 +0000
|
||||||
|
Subject: [PATCH 6/8] mark checkable toolbox menu entries as checkable
|
||||||
|
|
||||||
|
e.g. the toplevel toolbars put excess entries in
|
||||||
|
menus. If the entry is not marked as checkable then
|
||||||
|
a native gtk menu entry will appear to be stateless
|
||||||
|
when it actually does have a toggle state
|
||||||
|
|
||||||
|
Change-Id: I7168b44d59fd64dfe264ed8ca26355252d697251
|
||||||
|
(cherry picked from commit 13917e0755bb864f22d0cf75a43854acbdb1eaec)
|
||||||
|
---
|
||||||
|
vcl/source/window/toolbox2.cxx | 20 ++++++++++++++++++--
|
||||||
|
1 file changed, 18 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/vcl/source/window/toolbox2.cxx b/vcl/source/window/toolbox2.cxx
|
||||||
|
index 0c916f6..663b7d6 100644
|
||||||
|
--- a/vcl/source/window/toolbox2.cxx
|
||||||
|
+++ b/vcl/source/window/toolbox2.cxx
|
||||||
|
@@ -1791,6 +1791,20 @@ bool ToolBox::ImplHasClippedItems()
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
+namespace
|
||||||
|
+{
|
||||||
|
+ MenuItemBits ConvertBitsFromToolBoxToMenu(ToolBoxItemBits nToolItemBits)
|
||||||
|
+ {
|
||||||
|
+ MenuItemBits nMenuItemBits = MenuItemBits::NONE;
|
||||||
|
+ if ((nToolItemBits & ToolBoxItemBits::CHECKABLE) ||
|
||||||
|
+ (nToolItemBits & ToolBoxItemBits::DROPDOWN))
|
||||||
|
+ {
|
||||||
|
+ nMenuItemBits |= MenuItemBits::CHECKABLE;
|
||||||
|
+ }
|
||||||
|
+ return nMenuItemBits;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void ToolBox::UpdateCustomMenu()
|
||||||
|
{
|
||||||
|
// fill clipped items into menu
|
||||||
|
@@ -1826,7 +1840,8 @@ void ToolBox::UpdateCustomMenu()
|
||||||
|
if( it->IsClipped() )
|
||||||
|
{
|
||||||
|
sal_uInt16 id = it->mnId + TOOLBOX_MENUITEM_START;
|
||||||
|
- pMenu->InsertItem( id, it->maText, it->maImageOriginal, MenuItemBits::NONE, OString());
|
||||||
|
+ MenuItemBits nMenuItemBits = ConvertBitsFromToolBoxToMenu(it->mnBits);
|
||||||
|
+ pMenu->InsertItem( id, it->maText, it->maImageOriginal, nMenuItemBits, OString());
|
||||||
|
pMenu->SetItemCommand( id, it->maCommandStr );
|
||||||
|
pMenu->EnableItem( id, it->mbEnabled );
|
||||||
|
pMenu->CheckItem ( id, it->meState == TRISTATE_TRUE );
|
||||||
|
@@ -1843,7 +1858,8 @@ void ToolBox::UpdateCustomMenu()
|
||||||
|
if( it->IsItemHidden() )
|
||||||
|
{
|
||||||
|
sal_uInt16 id = it->mnId + TOOLBOX_MENUITEM_START;
|
||||||
|
- pMenu->InsertItem( id, it->maText, it->maImageOriginal, MenuItemBits::NONE, OString() );
|
||||||
|
+ MenuItemBits nMenuItemBits = ConvertBitsFromToolBoxToMenu(it->mnBits);
|
||||||
|
+ pMenu->InsertItem( id, it->maText, it->maImageOriginal, nMenuItemBits, OString() );
|
||||||
|
pMenu->SetItemCommand( id, it->maCommandStr );
|
||||||
|
pMenu->EnableItem( id, it->mbEnabled );
|
||||||
|
pMenu->CheckItem( id, it->meState == TRISTATE_TRUE );
|
||||||
|
--
|
||||||
|
2.7.1
|
||||||
|
|
@ -0,0 +1,26 @@
|
|||||||
|
From 205dd9979f77c709cf36b92da1836ce5374879ab Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com>
|
||||||
|
Date: Wed, 24 Feb 2016 15:24:53 +0000
|
||||||
|
Subject: [PATCH 7/8] set gtk layout direction to match ours
|
||||||
|
|
||||||
|
Change-Id: I27610f28f42368355bef1b3461fc3ccea1b07218
|
||||||
|
(cherry picked from commit b50071c817657866f8b22873be26d34970005a2d)
|
||||||
|
---
|
||||||
|
vcl/unx/gtk/gtkdata.cxx | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/vcl/unx/gtk/gtkdata.cxx b/vcl/unx/gtk/gtkdata.cxx
|
||||||
|
index 9ea6dc9..f15cce2 100644
|
||||||
|
--- a/vcl/unx/gtk/gtkdata.cxx
|
||||||
|
+++ b/vcl/unx/gtk/gtkdata.cxx
|
||||||
|
@@ -110,6 +110,7 @@ GtkSalDisplay::GtkSalDisplay( GdkDisplay* pDisplay ) :
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+ gtk_widget_set_default_direction(AllSettings::GetLayoutRTL() ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkSalDisplay::~GtkSalDisplay()
|
||||||
|
--
|
||||||
|
2.7.1
|
||||||
|
|
@ -0,0 +1,550 @@
|
|||||||
|
From b265bcddde36bea2f5b31ce5df407301cbfe82b5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com>
|
||||||
|
Date: Tue, 23 Feb 2016 15:57:11 +0000
|
||||||
|
Subject: [PATCH 8/8] gtk3: implement native context menus
|
||||||
|
|
||||||
|
This reuses lots of the unity machinery which is similar
|
||||||
|
to the mac concept of a single toplevel menubar.
|
||||||
|
|
||||||
|
So to drive popup menus, part of this is a rework that does away with the idea
|
||||||
|
that the "menubar" is the controller of the hierarchy, and instead the top
|
||||||
|
element becomes the controller
|
||||||
|
|
||||||
|
Change-Id: I4336391718844bc73cfc47c1043f99f0e3b812d8
|
||||||
|
(cherry picked from commit a0c700b1493c7b51540d1e77b44d1edd9bf920f0)
|
||||||
|
---
|
||||||
|
vcl/inc/unx/gtk/gloactiongroup.h | 3 +
|
||||||
|
vcl/inc/unx/gtk/gtksalmenu.hxx | 9 +-
|
||||||
|
vcl/unx/gtk/gloactiongroup.cxx | 43 ++++----
|
||||||
|
vcl/unx/gtk/gtksalmenu.cxx | 228 +++++++++++++++++++++++++++++----------
|
||||||
|
4 files changed, 203 insertions(+), 80 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/vcl/inc/unx/gtk/gloactiongroup.h b/vcl/inc/unx/gtk/gloactiongroup.h
|
||||||
|
index 080b679..ec6bd39 100644
|
||||||
|
--- a/vcl/inc/unx/gtk/gloactiongroup.h
|
||||||
|
+++ b/vcl/inc/unx/gtk/gloactiongroup.h
|
||||||
|
@@ -46,6 +46,9 @@ GType g_lo_action_group_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
GLOActionGroup * g_lo_action_group_new (gpointer frame);
|
||||||
|
|
||||||
|
+void g_lo_action_group_set_top_menu (GLOActionGroup *group,
|
||||||
|
+ gpointer top_menu);
|
||||||
|
+
|
||||||
|
void g_lo_action_group_insert (GLOActionGroup *group,
|
||||||
|
const gchar *action_name,
|
||||||
|
gint item_id,
|
||||||
|
diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx
|
||||||
|
index 1d58b7a..d95d25c 100644
|
||||||
|
--- a/vcl/inc/unx/gtk/gtksalmenu.hxx
|
||||||
|
+++ b/vcl/inc/unx/gtk/gtksalmenu.hxx
|
||||||
|
@@ -43,16 +43,17 @@ private:
|
||||||
|
std::vector< GtkSalMenuItem* > maItems;
|
||||||
|
|
||||||
|
bool mbMenuBar;
|
||||||
|
+ bool mbMenuVisibility;
|
||||||
|
Menu* mpVCLMenu;
|
||||||
|
GtkSalMenu* mpParentSalMenu;
|
||||||
|
- const GtkSalFrame* mpFrame;
|
||||||
|
+ GtkSalFrame* mpFrame;
|
||||||
|
|
||||||
|
// GMenuModel and GActionGroup attributes
|
||||||
|
GMenuModel* mpMenuModel;
|
||||||
|
GActionGroup* mpActionGroup;
|
||||||
|
|
||||||
|
GtkSalMenu* GetMenuForItemCommand( gchar* aCommand, gboolean bGetSubmenu );
|
||||||
|
- void ImplUpdate( gboolean bRecurse );
|
||||||
|
+ void ImplUpdate(bool bRecurse, bool bRemoveDisabledEntries);
|
||||||
|
void ActivateAllSubmenus(Menu* pMenuBar);
|
||||||
|
|
||||||
|
public:
|
||||||
|
@@ -77,7 +78,7 @@ public:
|
||||||
|
|
||||||
|
void SetMenu( Menu* pMenu ) { mpVCLMenu = pMenu; }
|
||||||
|
Menu* GetMenu() { return mpVCLMenu; }
|
||||||
|
- void SetMenuModel( GMenuModel* pMenuModel ) { mpMenuModel = pMenuModel; }
|
||||||
|
+ void SetMenuModel(GMenuModel* pMenuModel);
|
||||||
|
unsigned GetItemCount() { return maItems.size(); }
|
||||||
|
GtkSalMenuItem* GetItemAtPos( unsigned nPos ) { return maItems[ nPos ]; }
|
||||||
|
void SetActionGroup( GActionGroup* pActionGroup ) { mpActionGroup = pActionGroup; }
|
||||||
|
@@ -102,6 +103,8 @@ public:
|
||||||
|
bool PrepUpdate();
|
||||||
|
virtual void Update() override; // Update this menu only.
|
||||||
|
void UpdateFull(); // Update full menu hierarchy from this menu.
|
||||||
|
+
|
||||||
|
+ virtual bool ShowNativePopupMenu(FloatingWindow * pWin, const Rectangle& rRect, FloatWinPopupFlags nFlags) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GtkSalMenuItem : public SalMenuItem
|
||||||
|
diff --git a/vcl/unx/gtk/gloactiongroup.cxx b/vcl/unx/gtk/gloactiongroup.cxx
|
||||||
|
index e710809..110e0dc 100644
|
||||||
|
--- a/vcl/unx/gtk/gloactiongroup.cxx
|
||||||
|
+++ b/vcl/unx/gtk/gloactiongroup.cxx
|
||||||
|
@@ -100,8 +100,9 @@ g_lo_action_class_init (GLOActionClass *klass)
|
||||||
|
|
||||||
|
struct _GLOActionGroupPrivate
|
||||||
|
{
|
||||||
|
- GHashTable *table; /* string -> GLOAction */
|
||||||
|
- GtkSalFrame *frame; /* Frame to which GActionGroup is associated. */
|
||||||
|
+ GHashTable *table; /* string -> GLOAction */
|
||||||
|
+ GtkSalFrame *frame; /* Frame to which GActionGroup is associated. */
|
||||||
|
+ GtkSalMenu *topmenu; /* TopLevel Menu to which GActionGroup is associated. */
|
||||||
|
};
|
||||||
|
|
||||||
|
static void g_lo_action_group_iface_init (GActionGroupInterface *);
|
||||||
|
@@ -187,13 +188,7 @@ g_lo_action_group_perform_submenu_action (GLOActionGroup *group,
|
||||||
|
GVariant *state)
|
||||||
|
{
|
||||||
|
|
||||||
|
- GtkSalFrame* pFrame = group->priv->frame;
|
||||||
|
- SAL_INFO("vcl.unity", "g_lo_action_group_perform_submenu_action on " << group << " for frame " << pFrame);
|
||||||
|
-
|
||||||
|
- if (pFrame == nullptr)
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
- GtkSalMenu* pSalMenu = static_cast<GtkSalMenu*> (pFrame->GetMenu());
|
||||||
|
+ GtkSalMenu* pSalMenu = group->priv->topmenu;
|
||||||
|
SAL_INFO("vcl.unity", "g_lo_action_group_perform_submenu_action on " << group << " for menu " << pSalMenu);
|
||||||
|
|
||||||
|
if (pSalMenu != nullptr) {
|
||||||
|
@@ -263,23 +258,18 @@ g_lo_action_group_activate (GActionGroup *group,
|
||||||
|
GVariant *parameter)
|
||||||
|
{
|
||||||
|
GLOActionGroup *lo_group = G_LO_ACTION_GROUP (group);
|
||||||
|
- GtkSalFrame *pFrame = lo_group->priv->frame;
|
||||||
|
- SAL_INFO("vcl.unity", "g_lo_action_group_activate on group " << group << " for frame " << pFrame << " with parameter " << parameter);
|
||||||
|
+ GtkSalMenu* pSalMenu = lo_group->priv->topmenu;
|
||||||
|
|
||||||
|
if ( parameter != nullptr )
|
||||||
|
g_action_group_change_action_state( group, action_name, parameter );
|
||||||
|
|
||||||
|
- if ( pFrame != nullptr )
|
||||||
|
- {
|
||||||
|
- GtkSalMenu* pSalMenu = static_cast< GtkSalMenu* >( pFrame->GetMenu() );
|
||||||
|
- SAL_INFO("vcl.unity", "g_lo_action_group_activate for menu " << pSalMenu);
|
||||||
|
+ SAL_INFO("vcl.unity", "g_lo_action_group_activate for menu " << pSalMenu);
|
||||||
|
|
||||||
|
- if ( pSalMenu != nullptr )
|
||||||
|
- {
|
||||||
|
- GLOAction* action = G_LO_ACTION (g_hash_table_lookup (lo_group->priv->table, action_name));
|
||||||
|
- SAL_INFO("vcl.unity", "g_lo_action_group_activate dispatching action " << action << " named " << action_name << " on menu " << pSalMenu);
|
||||||
|
- pSalMenu->DispatchCommand( action->item_id, action_name );
|
||||||
|
- }
|
||||||
|
+ if ( pSalMenu != nullptr )
|
||||||
|
+ {
|
||||||
|
+ GLOAction* action = G_LO_ACTION (g_hash_table_lookup (lo_group->priv->table, action_name));
|
||||||
|
+ SAL_INFO("vcl.unity", "g_lo_action_group_activate dispatching action " << action << " named " << action_name << " on menu " << pSalMenu);
|
||||||
|
+ pSalMenu->DispatchCommand( action->item_id, action_name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -355,6 +345,17 @@ g_lo_action_group_init (GLOActionGroup *group)
|
||||||
|
group->priv->table = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
|
g_free, g_object_unref);
|
||||||
|
group->priv->frame = nullptr;
|
||||||
|
+ group->priv->topmenu = nullptr;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+g_lo_action_group_set_top_menu (GLOActionGroup *group,
|
||||||
|
+ gpointer top_menu)
|
||||||
|
+{
|
||||||
|
+ group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
|
||||||
|
+ G_TYPE_LO_ACTION_GROUP,
|
||||||
|
+ GLOActionGroupPrivate);
|
||||||
|
+ group->priv->topmenu = static_cast<GtkSalMenu*>(top_menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
diff --git a/vcl/unx/gtk/gtksalmenu.cxx b/vcl/unx/gtk/gtksalmenu.cxx
|
||||||
|
index 346e42d..7bc9232 100644
|
||||||
|
--- a/vcl/unx/gtk/gtksalmenu.cxx
|
||||||
|
+++ b/vcl/unx/gtk/gtksalmenu.cxx
|
||||||
|
@@ -16,6 +16,7 @@
|
||||||
|
#include <unx/gtk/gtkdata.hxx>
|
||||||
|
#include <unx/gtk/glomenu.h>
|
||||||
|
#include <unx/gtk/gloactiongroup.h>
|
||||||
|
+#include <vcl/floatwin.hxx>
|
||||||
|
#include <vcl/menu.hxx>
|
||||||
|
#include <unx/gtk/gtkinst.hxx>
|
||||||
|
|
||||||
|
@@ -24,6 +25,7 @@
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sal/log.hxx>
|
||||||
|
+#include <window.h>
|
||||||
|
|
||||||
|
// FIXME Copied from framework/inc/framework/menuconfiguration.hxx to
|
||||||
|
// avoid circular dependency between modules. It should be in a common
|
||||||
|
@@ -31,8 +33,6 @@
|
||||||
|
const sal_uInt16 START_ITEMID_WINDOWLIST = 4600;
|
||||||
|
const sal_uInt16 END_ITEMID_WINDOWLIST = 4699;
|
||||||
|
|
||||||
|
-static bool bMenuVisibility = false;
|
||||||
|
-
|
||||||
|
/*
|
||||||
|
* This function generates the proper command name for all actions, including
|
||||||
|
* duplicated or special ones.
|
||||||
|
@@ -77,20 +77,17 @@ static gchar* GetCommandForItem( GtkSalMenuItem* pSalMenuItem, gchar* aCurrentCo
|
||||||
|
|
||||||
|
bool GtkSalMenu::PrepUpdate()
|
||||||
|
{
|
||||||
|
- const GtkSalFrame* pFrame = GetFrame();
|
||||||
|
- if (pFrame)
|
||||||
|
- {
|
||||||
|
- GtkSalFrame* pNonConstFrame = const_cast<GtkSalFrame*>(pFrame);
|
||||||
|
- GtkSalMenu* pSalMenu = this;
|
||||||
|
-
|
||||||
|
- if ( !pNonConstFrame->GetMenu() )
|
||||||
|
- pNonConstFrame->SetMenu( pSalMenu );
|
||||||
|
+ bool bMenuVisibility;
|
||||||
|
|
||||||
|
- if ( bMenuVisibility && mpMenuModel && mpActionGroup )
|
||||||
|
- return true;
|
||||||
|
- }
|
||||||
|
+ //get top level visibility
|
||||||
|
+ const GtkSalMenu* pMenu = this;
|
||||||
|
+ do
|
||||||
|
+ {
|
||||||
|
+ bMenuVisibility = pMenu->mbMenuVisibility;
|
||||||
|
+ pMenu = pMenu->mpParentSalMenu;
|
||||||
|
+ } while (pMenu);
|
||||||
|
|
||||||
|
- return false;
|
||||||
|
+ return bMenuVisibility && mpMenuModel && mpActionGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -114,14 +111,58 @@ void RemoveSpareItemsFromNativeMenu( GLOMenu* pMenu, GList** pOldCommandList, un
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-void RemoveSpareSectionsFromNativeMenu( GLOMenu* pMenu, GList** pOldCommandList, unsigned nLastSection )
|
||||||
|
+void RemoveDisabledItemsFromNativeMenu(GLOMenu* pMenu, GList** pOldCommandList,
|
||||||
|
+ sal_Int32 nSection, GActionGroup* pActionGroup)
|
||||||
|
+{
|
||||||
|
+ while (nSection >= 0)
|
||||||
|
+ {
|
||||||
|
+ sal_Int32 nSectionItems = g_lo_menu_get_n_items_from_section( pMenu, nSection );
|
||||||
|
+ while (nSectionItems--)
|
||||||
|
+ {
|
||||||
|
+ gchar* pCommand = g_lo_menu_get_command_from_item_in_section(pMenu, nSection, nSectionItems);
|
||||||
|
+ // remove disabled entries
|
||||||
|
+ bool bRemove = g_action_group_get_action_enabled(pActionGroup, pCommand) == false;
|
||||||
|
+ if (!bRemove)
|
||||||
|
+ {
|
||||||
|
+ //also remove any empty submenus
|
||||||
|
+ GLOMenu* pSubMenuModel = g_lo_menu_get_submenu_from_item_in_section(pMenu, nSection, nSectionItems);
|
||||||
|
+ if (pSubMenuModel)
|
||||||
|
+ {
|
||||||
|
+ gint nSubMenuSections = g_menu_model_get_n_items(G_MENU_MODEL(pSubMenuModel));
|
||||||
|
+ bRemove = (nSubMenuSections == 0 ||
|
||||||
|
+ (nSubMenuSections == 1 && g_lo_menu_get_n_items_from_section(pSubMenuModel, 0) == 0));
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (bRemove)
|
||||||
|
+ {
|
||||||
|
+ //but tdf#86850 Always display clipboard functions
|
||||||
|
+ bRemove = g_strcmp0(pCommand, ".uno:Cut") &&
|
||||||
|
+ g_strcmp0(pCommand, ".uno:Copy") &&
|
||||||
|
+ g_strcmp0(pCommand, ".uno:Paste");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (bRemove)
|
||||||
|
+ {
|
||||||
|
+ if (pCommand != nullptr && pOldCommandList != nullptr)
|
||||||
|
+ *pOldCommandList = g_list_append(*pOldCommandList, g_strdup(pCommand));
|
||||||
|
+ g_lo_menu_remove_from_section(pMenu, nSection, nSectionItems);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ g_free(pCommand);
|
||||||
|
+ }
|
||||||
|
+ --nSection;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void RemoveSpareSectionsFromNativeMenu( GLOMenu* pMenu, GList** pOldCommandList, sal_Int32 nLastSection )
|
||||||
|
{
|
||||||
|
if ( pMenu == nullptr || pOldCommandList == nullptr )
|
||||||
|
return;
|
||||||
|
|
||||||
|
sal_Int32 n = g_menu_model_get_n_items( G_MENU_MODEL( pMenu ) ) - 1;
|
||||||
|
|
||||||
|
- for ( ; n > (sal_Int32) nLastSection; n-- )
|
||||||
|
+ for ( ; n > nLastSection; n--)
|
||||||
|
{
|
||||||
|
RemoveSpareItemsFromNativeMenu( pMenu, pOldCommandList, n, 0 );
|
||||||
|
g_lo_menu_remove( pMenu, n );
|
||||||
|
@@ -173,7 +214,7 @@ void RemoveUnusedCommands( GLOActionGroup* pActionGroup, GList* pOldCommandList,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-void GtkSalMenu::ImplUpdate( gboolean bRecurse )
|
||||||
|
+void GtkSalMenu::ImplUpdate(bool bRecurse, bool bRemoveDisabledEntries)
|
||||||
|
{
|
||||||
|
SolarMutexGuard aGuard;
|
||||||
|
|
||||||
|
@@ -277,7 +318,7 @@ void GtkSalMenu::ImplUpdate( gboolean bRecurse )
|
||||||
|
SAL_INFO("vcl.unity", "preparing submenu " << pSubMenuModel << " to menu model " << G_MENU_MODEL(pSubMenuModel) << " and action group " << G_ACTION_GROUP(pActionGroup));
|
||||||
|
pSubmenu->SetMenuModel( G_MENU_MODEL( pSubMenuModel ) );
|
||||||
|
pSubmenu->SetActionGroup( G_ACTION_GROUP( pActionGroup ) );
|
||||||
|
- pSubmenu->ImplUpdate( bRecurse );
|
||||||
|
+ pSubmenu->ImplUpdate(bRecurse, bRemoveDisabledEntries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -287,6 +328,12 @@ void GtkSalMenu::ImplUpdate( gboolean bRecurse )
|
||||||
|
++validItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (bRemoveDisabledEntries)
|
||||||
|
+ {
|
||||||
|
+ // Delete disabled items in last section.
|
||||||
|
+ RemoveDisabledItemsFromNativeMenu(pLOMenu, &pOldCommandList, nSection, G_ACTION_GROUP(pActionGroup));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
// Delete extra items in last section.
|
||||||
|
RemoveSpareItemsFromNativeMenu( pLOMenu, &pOldCommandList, nSection, validItems );
|
||||||
|
|
||||||
|
@@ -299,12 +346,89 @@ void GtkSalMenu::ImplUpdate( gboolean bRecurse )
|
||||||
|
|
||||||
|
void GtkSalMenu::Update()
|
||||||
|
{
|
||||||
|
- ImplUpdate( FALSE );
|
||||||
|
+ //find out if top level is a menubar or not, if not, then its a popup menu
|
||||||
|
+ //hierarchy and in those we hide (most) disabled entries
|
||||||
|
+ const GtkSalMenu* pMenu = this;
|
||||||
|
+ while (pMenu->mpParentSalMenu)
|
||||||
|
+ pMenu = pMenu->mpParentSalMenu;
|
||||||
|
+ ImplUpdate(false, !pMenu->mbMenuBar);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GtkSalMenu::UpdateFull()
|
||||||
|
{
|
||||||
|
- ImplUpdate( TRUE );
|
||||||
|
+ //find out if top level is a menubar or not, if not, then its a popup menu
|
||||||
|
+ //hierarchy and in those we hide (most) disabled entries
|
||||||
|
+ const GtkSalMenu* pMenu = this;
|
||||||
|
+ while (pMenu->mpParentSalMenu)
|
||||||
|
+ pMenu = pMenu->mpParentSalMenu;
|
||||||
|
+ ImplUpdate(true, !pMenu->mbMenuBar);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+bool GtkSalMenu::ShowNativePopupMenu(FloatingWindow* pWin, const Rectangle& /*rRect*/,
|
||||||
|
+ FloatWinPopupFlags /*nFlags*/)
|
||||||
|
+{
|
||||||
|
+#if GTK_CHECK_VERSION(3,0,0)
|
||||||
|
+ guint nButton;
|
||||||
|
+ guint32 nTime;
|
||||||
|
+
|
||||||
|
+ //typically there is an event, and we can then distinguish if this was
|
||||||
|
+ //launched from the keyboard (gets auto-mnemoniced) or the mouse (which
|
||||||
|
+ //doesn't)
|
||||||
|
+ GdkEvent *pEvent = gtk_get_current_event();
|
||||||
|
+ if (pEvent)
|
||||||
|
+ {
|
||||||
|
+ gdk_event_get_button(pEvent, &nButton);
|
||||||
|
+ nTime = gdk_event_get_time(pEvent);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ nButton = 0;
|
||||||
|
+ nTime = gtk_get_current_event_time();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ Display(true);
|
||||||
|
+
|
||||||
|
+ mpFrame = static_cast<GtkSalFrame*>(pWin->ImplGetWindowImpl()->mpRealParent->ImplGetFrame());
|
||||||
|
+
|
||||||
|
+ GLOActionGroup* pActionGroup = g_lo_action_group_new(static_cast<gpointer>(mpFrame));
|
||||||
|
+ g_lo_action_group_set_top_menu(pActionGroup, static_cast<gpointer>(this));
|
||||||
|
+
|
||||||
|
+ mpActionGroup = G_ACTION_GROUP(pActionGroup);
|
||||||
|
+ mpMenuModel = G_MENU_MODEL(g_lo_menu_new());
|
||||||
|
+ // Generate the main menu structure, populates mpMenuModel
|
||||||
|
+ UpdateFull();
|
||||||
|
+
|
||||||
|
+ GtkWidget *pWidget = gtk_menu_new_from_model(mpMenuModel);
|
||||||
|
+ gtk_menu_attach_to_widget(GTK_MENU(pWidget), mpFrame->getMouseEventWidget(), nullptr);
|
||||||
|
+
|
||||||
|
+ gtk_widget_insert_action_group(mpFrame->getMouseEventWidget(), "win", mpActionGroup);
|
||||||
|
+
|
||||||
|
+ //run in a sub main loop because we need to keep vcl PopupMenu alive to use
|
||||||
|
+ //it during DispatchCommand, returning now to the outer loop causes the
|
||||||
|
+ //launching PopupMenu to be destroyed, instead run the subloop here
|
||||||
|
+ //until the gtk menu is destroyed
|
||||||
|
+ GMainLoop* pLoop = g_main_loop_new(nullptr, true);
|
||||||
|
+ g_signal_connect_swapped(G_OBJECT(pWidget), "deactivate", G_CALLBACK(g_main_loop_quit), pLoop);
|
||||||
|
+ gtk_menu_popup(GTK_MENU(pWidget), nullptr, nullptr, nullptr, nullptr, nButton, nTime);
|
||||||
|
+ if (g_main_loop_is_running(pLoop))
|
||||||
|
+ {
|
||||||
|
+ gdk_threads_leave();
|
||||||
|
+ g_main_loop_run(pLoop);
|
||||||
|
+ gdk_threads_enter();
|
||||||
|
+ }
|
||||||
|
+ g_main_loop_unref(pLoop);
|
||||||
|
+
|
||||||
|
+ gtk_widget_insert_action_group(mpFrame->getMouseEventWidget(), "win", nullptr);
|
||||||
|
+
|
||||||
|
+ gtk_widget_destroy(pWidget);
|
||||||
|
+
|
||||||
|
+ g_object_unref(mpActionGroup);
|
||||||
|
+
|
||||||
|
+ return true;
|
||||||
|
+#else
|
||||||
|
+ (void)pWin;
|
||||||
|
+ return false;
|
||||||
|
+#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -313,6 +437,7 @@ void GtkSalMenu::UpdateFull()
|
||||||
|
|
||||||
|
GtkSalMenu::GtkSalMenu( bool bMenuBar ) :
|
||||||
|
mbMenuBar( bMenuBar ),
|
||||||
|
+ mbMenuVisibility( false ),
|
||||||
|
mpVCLMenu( nullptr ),
|
||||||
|
mpParentSalMenu( nullptr ),
|
||||||
|
mpFrame( nullptr ),
|
||||||
|
@@ -321,25 +446,28 @@ GtkSalMenu::GtkSalMenu( bool bMenuBar ) :
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
+void GtkSalMenu::SetMenuModel(GMenuModel* pMenuModel)
|
||||||
|
+{
|
||||||
|
+ if (mpMenuModel)
|
||||||
|
+ g_object_unref(mpMenuModel);
|
||||||
|
+ mpMenuModel = pMenuModel;
|
||||||
|
+ if (mpMenuModel)
|
||||||
|
+ g_object_ref(mpMenuModel);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
GtkSalMenu::~GtkSalMenu()
|
||||||
|
{
|
||||||
|
SolarMutexGuard aGuard;
|
||||||
|
|
||||||
|
- if ( mbMenuBar )
|
||||||
|
- {
|
||||||
|
- if ( mpMenuModel )
|
||||||
|
- {
|
||||||
|
-// g_lo_menu_remove( G_LO_MENU( mpMenuModel ), 0 );
|
||||||
|
- g_object_unref( mpMenuModel );
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ if (mpMenuModel)
|
||||||
|
+ g_object_unref(mpMenuModel);
|
||||||
|
|
||||||
|
maItems.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GtkSalMenu::VisibleMenuBar()
|
||||||
|
{
|
||||||
|
- return bMenuVisibility;
|
||||||
|
+ return mbMenuBar && mbMenuVisibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GtkSalMenu::InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos )
|
||||||
|
@@ -374,22 +502,21 @@ void GtkSalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsig
|
||||||
|
pItem->mpSubMenu = pGtkSubMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
-void GtkSalMenu::SetFrame( const SalFrame* pFrame )
|
||||||
|
+void GtkSalMenu::SetFrame(const SalFrame* pFrame)
|
||||||
|
{
|
||||||
|
SolarMutexGuard aGuard;
|
||||||
|
assert(mbMenuBar);
|
||||||
|
SAL_INFO("vcl.unity", "GtkSalMenu set to frame");
|
||||||
|
- mpFrame = static_cast< const GtkSalFrame* >( pFrame );
|
||||||
|
- GtkSalFrame* pFrameNonConst = const_cast<GtkSalFrame*>(mpFrame);
|
||||||
|
+ mpFrame = const_cast<GtkSalFrame*>(static_cast<const GtkSalFrame*>(pFrame));
|
||||||
|
|
||||||
|
// if we had a menu on the GtkSalMenu we have to free it as we generate a
|
||||||
|
// full menu anyway and we might need to reuse an existing model and
|
||||||
|
// actiongroup
|
||||||
|
- pFrameNonConst->SetMenu( this );
|
||||||
|
- pFrameNonConst->EnsureAppMenuWatch();
|
||||||
|
+ mpFrame->SetMenu( this );
|
||||||
|
+ mpFrame->EnsureAppMenuWatch();
|
||||||
|
|
||||||
|
// Clean menu model and action group if needed.
|
||||||
|
- GtkWidget* pWidget = pFrameNonConst->getWindow();
|
||||||
|
+ GtkWidget* pWidget = mpFrame->getWindow();
|
||||||
|
GdkWindow* gdkWindow = gtk_widget_get_window( pWidget );
|
||||||
|
|
||||||
|
GLOMenu* pMenuModel = G_LO_MENU( g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-menubar" ) );
|
||||||
|
@@ -407,11 +534,12 @@ void GtkSalMenu::SetFrame( const SalFrame* pFrame )
|
||||||
|
if ( pActionGroup )
|
||||||
|
{
|
||||||
|
g_lo_action_group_clear( pActionGroup );
|
||||||
|
+ g_lo_action_group_set_top_menu(pActionGroup, static_cast<gpointer>(this));
|
||||||
|
mpActionGroup = G_ACTION_GROUP( pActionGroup );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate the main menu structure.
|
||||||
|
- if (bMenuVisibility)
|
||||||
|
+ if (mbMenuVisibility)
|
||||||
|
UpdateFull();
|
||||||
|
|
||||||
|
g_lo_menu_insert_section( pMenuModel, 0, nullptr, mpMenuModel );
|
||||||
|
@@ -618,14 +746,9 @@ GtkSalMenu* GtkSalMenu::GetMenuForItemCommand( gchar* aCommand, gboolean bGetSub
|
||||||
|
void GtkSalMenu::DispatchCommand( gint itemId, const gchar *aCommand )
|
||||||
|
{
|
||||||
|
SolarMutexGuard aGuard;
|
||||||
|
- // Only the menubar is allowed to dispatch commands.
|
||||||
|
- if ( !mbMenuBar )
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
GtkSalMenu* pSalSubMenu = GetMenuForItemCommand( const_cast<gchar*>(aCommand), FALSE );
|
||||||
|
Menu* pSubMenu = ( pSalSubMenu != nullptr ) ? pSalSubMenu->GetMenu() : nullptr;
|
||||||
|
-
|
||||||
|
- mpVCLMenu->HandleMenuCommandEvent( pSubMenu, itemId );
|
||||||
|
+ mpVCLMenu->HandleMenuCommandEvent(pSubMenu, itemId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GtkSalMenu::ActivateAllSubmenus(Menu* pMenuBar)
|
||||||
|
@@ -645,9 +768,6 @@ void GtkSalMenu::ActivateAllSubmenus(Menu* pMenuBar)
|
||||||
|
|
||||||
|
void GtkSalMenu::Activate( const gchar* aMenuCommand )
|
||||||
|
{
|
||||||
|
- if ( !mbMenuBar )
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
if ( !aMenuCommand ) {
|
||||||
|
ActivateAllSubmenus(mpVCLMenu);
|
||||||
|
return;
|
||||||
|
@@ -663,9 +783,6 @@ void GtkSalMenu::Activate( const gchar* aMenuCommand )
|
||||||
|
|
||||||
|
void GtkSalMenu::Deactivate( const gchar* aMenuCommand )
|
||||||
|
{
|
||||||
|
- if ( !mbMenuBar )
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
GtkSalMenu* pSalSubMenu = GetMenuForItemCommand( const_cast<gchar*>(aMenuCommand), TRUE );
|
||||||
|
|
||||||
|
if ( pSalSubMenu != nullptr ) {
|
||||||
|
@@ -675,15 +792,14 @@ void GtkSalMenu::Deactivate( const gchar* aMenuCommand )
|
||||||
|
|
||||||
|
void GtkSalMenu::Display( bool bVisible )
|
||||||
|
{
|
||||||
|
- if ( !mbMenuBar || mpVCLMenu == nullptr )
|
||||||
|
- return;
|
||||||
|
+ mbMenuVisibility = bVisible;
|
||||||
|
|
||||||
|
- bMenuVisibility = bVisible;
|
||||||
|
-
|
||||||
|
- bool bVCLMenuVisible = !bVisible;
|
||||||
|
-
|
||||||
|
- MenuBar* pMenuBar = static_cast< MenuBar* >( mpVCLMenu );
|
||||||
|
- pMenuBar->SetDisplayable( bVCLMenuVisible );
|
||||||
|
+ if (mbMenuBar)
|
||||||
|
+ {
|
||||||
|
+ bool bVCLMenuVisible = !bVisible;
|
||||||
|
+ MenuBar* pMenuBar = static_cast<MenuBar*>(mpVCLMenu);
|
||||||
|
+ pMenuBar->SetDisplayable(bVCLMenuVisible);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GtkSalMenu::IsItemVisible( unsigned nPos )
|
||||||
|
--
|
||||||
|
2.7.1
|
||||||
|
|
Loading…
Reference in new issue