From 1f4f5a55556dae157eaeec14d34f3f706d93b983 Mon Sep 17 00:00:00 2001 From: Antonio Fernandez Date: Tue, 11 Sep 2012 12:21:28 +0100 Subject: Fixed crashes when executing some menu actions. Change-Id: I80bb1ed74e823d4b66df05eb15c9b5ed2e58b7f6 --- vcl/inc/unx/gtk/gloactiongroup.h | 11 ++-- vcl/inc/unx/gtk/gtksalmenu.hxx | 1 + vcl/unx/gtk/window/gloactiongroup.cxx | 105 ++++++++++------------------------ vcl/unx/gtk/window/gtksalmenu.cxx | 50 ++++++++++++---- 4 files changed, 76 insertions(+), 91 deletions(-) (limited to 'vcl') diff --git a/vcl/inc/unx/gtk/gloactiongroup.h b/vcl/inc/unx/gtk/gloactiongroup.h index bc4d59d86a9c..e0d783fe3778 100644 --- a/vcl/inc/unx/gtk/gloactiongroup.h +++ b/vcl/inc/unx/gtk/gloactiongroup.h @@ -63,15 +63,15 @@ struct _GLOActionGroupClass GType g_lo_action_group_get_type (void) G_GNUC_CONST; -GLOActionGroup * g_lo_action_group_new (void); +GLOActionGroup * g_lo_action_group_new (gpointer frame); void g_lo_action_group_insert (GLOActionGroup *group, const gchar *action_name, - gpointer action_info); + gint item_id); void g_lo_action_group_insert_stateful (GLOActionGroup *group, const gchar *action_name, - gpointer action_info, + gint item_id, const GVariantType *parameter_type, const GVariantType *state_type, GVariant *state_hint, @@ -79,10 +79,7 @@ void g_lo_action_group_insert_stateful (GLOActionGroup void g_lo_action_group_set_action_enabled (GLOActionGroup *group, const gchar *action_name, - gboolean enabled); - -gpointer g_lo_action_group_get_action_item (GLOActionGroup *group, - const gchar *action_name); + gboolean enabled); void g_lo_action_group_remove (GLOActionGroup *group, const gchar *action_name); diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx index ddb6a6bb6c26..f746b4bb2063 100644 --- a/vcl/inc/unx/gtk/gtksalmenu.hxx +++ b/vcl/inc/unx/gtk/gtksalmenu.hxx @@ -89,6 +89,7 @@ public: virtual GtkSalMenuItem* GetItemAtPos( unsigned nPos ) { return maItems[ nPos ]; } virtual void SetActionGroup( GActionGroup* pActionGroup ) { mpActionGroup = pActionGroup; } virtual GActionGroup* GetActionGroup() { return mpActionGroup; } + GtkSalMenu* GetMenuForItemCommand( gchar* aCommand ); void NativeSetItemText( unsigned nSection, unsigned nItemPos, const rtl::OUString& rText ); void NativeSetItemCommand( unsigned nSection, unsigned nItemPos, GtkSalMenuItem* pItem, const gchar* aCommandStr ); diff --git a/vcl/unx/gtk/window/gloactiongroup.cxx b/vcl/unx/gtk/window/gloactiongroup.cxx index d7eafbfc2c53..33e756c14229 100644 --- a/vcl/unx/gtk/window/gloactiongroup.cxx +++ b/vcl/unx/gtk/window/gloactiongroup.cxx @@ -28,10 +28,6 @@ #include #include -#include -#include - -using namespace std; /* * GLOAction @@ -47,7 +43,7 @@ struct _GLOAction { GObject parent_instance; - GtkSalMenuItem* item; // A pointer to the menu item. + gint item_id; // Menu item ID. gboolean enabled; // TRUE if action is enabled, FALSE otherwise. GVariantType* parameter_type; // A GVariantType with the action parameter type. GVariantType* state_type; // A GVariantType with item state type @@ -69,7 +65,7 @@ g_lo_action_new (void) static void g_lo_action_init (GLOAction *action) { - action->item = NULL; + action->item_id = -1; action->enabled = TRUE; action->parameter_type = NULL; action->state_type = NULL; @@ -82,8 +78,6 @@ g_lo_action_finalize (GObject *object) { GLOAction* action = G_LO_ACTION(object); - action->item = NULL; - if (action->parameter_type) g_variant_type_free (action->parameter_type); @@ -113,7 +107,8 @@ g_lo_action_class_init (GLOActionClass *klass) struct _GLOActionGroupPrivate { - GHashTable *table; /* string -> GtkSalMenuItem* */ + GHashTable *table; /* string -> GLOAction */ + GtkSalFrame *frame; /* Frame to which GActionGroup is associated. */ }; static void g_lo_action_group_iface_init (GActionGroupInterface *); @@ -218,67 +213,39 @@ g_lo_action_group_activate (GActionGroup *group, { GTK_YIELD_GRAB(); - GLOActionGroup *loGroup = G_LO_ACTION_GROUP (group); - GLOAction* action = G_LO_ACTION (g_hash_table_lookup (loGroup->priv->table, action_name)); - GtkSalMenuItem *pSalMenuItem = action->item; + GLOActionGroup *lo_group = G_LO_ACTION_GROUP (group); + GLOAction* action = G_LO_ACTION (g_hash_table_lookup (lo_group->priv->table, action_name)); - if (pSalMenuItem == NULL || pSalMenuItem->mpSubMenu ) + GtkSalFrame *pFrame = lo_group->priv->frame; + + if ( pFrame == NULL ) return; - const GtkSalFrame *pFrame = pSalMenuItem->mpParentMenu ? pSalMenuItem->mpParentMenu->GetFrame() : NULL; + GtkSalMenu* pSalMenu = static_cast< GtkSalMenu* >( pFrame->GetMenu() ); - if ( pFrame && !pFrame->GetParent() ) { - ((PopupMenu*) pSalMenuItem->mpVCLMenu)->SetSelectedEntry( pSalMenuItem->mnId ); - SalMenuEvent aMenuEvt( pSalMenuItem->mnId, pSalMenuItem->mpVCLMenu ); - pFrame->CallCallback( SALEVENT_MENUCOMMAND, &aMenuEvt ); - } - else if ( pSalMenuItem->mpVCLMenu ) - { - // if an item from submenu was selected. the corresponding Window does not exist because - // we use native popup menus, so we have to set the selected menuitem directly - // incidentally this of course works for top level popup menus, too - PopupMenu * pPopupMenu = dynamic_cast(pSalMenuItem->mpVCLMenu); - if( pPopupMenu ) - { - // FIXME: revise this ugly code - - // select handlers in vcl are dispatch on the original menu - // if not consumed by the select handler of the current menu - // however since only the starting menu ever came into Execute - // the hierarchy is not build up. Workaround this by getting - // the menu it should have been - - // get started from hierarchy in vcl menus - GtkSalMenu* pParentMenu = pSalMenuItem->mpParentMenu; - Menu* pCurMenu = pSalMenuItem->mpVCLMenu; - while( pParentMenu && pParentMenu->GetMenu() ) - { - pCurMenu = pParentMenu->GetMenu(); - pParentMenu = pParentMenu->GetParentSalMenu(); - } - - pPopupMenu->SetSelectedEntry( pSalMenuItem->mnId ); - pPopupMenu->ImplSelectWithStart( pCurMenu ); - } - else - { - OSL_FAIL( "menubar item without frame !" ); - } - } + if ( pSalMenu == NULL ) + return; + + GtkSalMenu* pSalSubMenu = pSalMenu->GetMenuForItemCommand( (gchar*) action_name ); + Menu* pSubMenu = ( pSalMenu != NULL ) ? pSalSubMenu->GetMenu() : NULL; + + MenuBar* pMenuBar = static_cast< MenuBar* >( pSalMenu->GetMenu() ); + + pMenuBar->HandleMenuCommandEvent( pSubMenu, action->item_id ); } void g_lo_action_group_insert (GLOActionGroup *group, const gchar *action_name, - gpointer action_info) + gint item_id) { - g_lo_action_group_insert_stateful (group, action_name, action_info, NULL, NULL, NULL, NULL); + g_lo_action_group_insert_stateful (group, action_name, item_id, NULL, NULL, NULL, NULL); } void g_lo_action_group_insert_stateful (GLOActionGroup *group, const gchar *action_name, - gpointer action_info, + gint item_id, const GVariantType *parameter_type, const GVariantType *state_type, GVariant *state_hint, @@ -288,7 +255,7 @@ g_lo_action_group_insert_stateful (GLOActionGroup *group, GLOAction* old_action = G_LO_ACTION (g_hash_table_lookup (group->priv->table, action_name)); - if (old_action == NULL || old_action->item != action_info) + if (old_action == NULL || old_action->item_id != item_id) { if (old_action != NULL) g_action_group_action_removed (G_ACTION_GROUP (group), action_name); @@ -297,7 +264,7 @@ g_lo_action_group_insert_stateful (GLOActionGroup *group, g_hash_table_insert (group->priv->table, g_strdup (action_name), action); - action->item = static_cast< GtkSalMenuItem* >( action_info ); + action->item_id = item_id; if (parameter_type) action->parameter_type = (GVariantType*) parameter_type; @@ -333,6 +300,7 @@ g_lo_action_group_init (GLOActionGroup *group) GLOActionGroupPrivate); group->priv->table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + group->priv->frame = NULL; } static void @@ -355,9 +323,12 @@ g_lo_action_group_iface_init (GActionGroupInterface *iface) } GLOActionGroup * -g_lo_action_group_new (void) +g_lo_action_group_new (gpointer frame) { - return G_LO_ACTION_GROUP( g_object_new (G_TYPE_LO_ACTION_GROUP, NULL) ); + GLOActionGroup* group = G_LO_ACTION_GROUP (g_object_new (G_TYPE_LO_ACTION_GROUP, NULL)); + group->priv->frame = static_cast< GtkSalFrame* > (frame); + + return group; } void @@ -375,21 +346,7 @@ g_lo_action_group_set_action_enabled (GLOActionGroup *group, action->enabled = enabled; - g_action_group_action_enabled_changed(G_ACTION_GROUP(group), - action_name, - enabled); -} - -gpointer -g_lo_action_group_get_action_item (GLOActionGroup *group, - const gchar *action_name) -{ - g_return_val_if_fail (G_IS_LO_ACTION_GROUP (group), NULL); - g_return_val_if_fail (action_name != NULL, NULL); - - GLOAction* action = G_LO_ACTION (g_hash_table_lookup (group->priv->table, action_name)); - - return (action != NULL) ? action->item : NULL; + g_action_group_action_enabled_changed (G_ACTION_GROUP (group), action_name, enabled); } void diff --git a/vcl/unx/gtk/window/gtksalmenu.cxx b/vcl/unx/gtk/window/gtksalmenu.cxx index 19ca8893a811..b61af316f4ab 100644 --- a/vcl/unx/gtk/window/gtksalmenu.cxx +++ b/vcl/unx/gtk/window/gtksalmenu.cxx @@ -367,19 +367,19 @@ void GtkSalMenu::SetFrame( const SalFrame* pFrame ) if ( mpMenuModel == NULL && mpActionGroup == NULL ) { mpMenuModel = G_MENU_MODEL( g_lo_menu_new() ); - mpActionGroup = G_ACTION_GROUP( g_lo_action_group_new() ); + mpActionGroup = G_ACTION_GROUP( g_lo_action_group_new( ( gpointer ) mpFrame ) ); g_object_set_data_full( G_OBJECT( gdkWindow ), "g-lo-menubar", mpMenuModel, ObjectDestroyedNotify ); g_object_set_data_full( G_OBJECT( gdkWindow ), "g-lo-action-group", mpActionGroup, ObjectDestroyedNotify ); // Publish the menu only if AppMenu registrar is available. guint nWatcherId = g_bus_watch_name (G_BUS_TYPE_SESSION, - "com.canonical.AppMenu.Registrar", - G_BUS_NAME_WATCHER_FLAGS_NONE, - on_registrar_available, - on_registrar_unavailable, - (gpointer) mpFrame, - NULL); + "com.canonical.AppMenu.Registrar", + G_BUS_NAME_WATCHER_FLAGS_NONE, + on_registrar_available, + on_registrar_unavailable, + (gpointer) mpFrame, + NULL); ( ( GtkSalFrame* ) mpFrame )->SetWatcherId( nWatcherId ); } @@ -512,7 +512,7 @@ void GtkSalMenu::NativeSetItemCommand( unsigned nSection, unsigned nItemPos, Gtk GVariantType* pStateType = g_variant_type_new( (gchar*) G_VARIANT_TYPE_BOOLEAN ); GVariant* pState = g_variant_new_boolean( bChecked ); - g_lo_action_group_insert_stateful( pActionGroup, aCommand, pItem, NULL, pStateType, NULL, pState ); + g_lo_action_group_insert_stateful( pActionGroup, aCommand, pItem->mnId, NULL, pStateType, NULL, pState ); } else if ( bits & MIB_RADIOCHECK ) { @@ -522,12 +522,12 @@ void GtkSalMenu::NativeSetItemCommand( unsigned nSection, unsigned nItemPos, Gtk GVariant* pState = g_variant_new_string( "" ); pTarget = g_variant_new_string( aCommand ); - g_lo_action_group_insert_stateful( pActionGroup, aCommand, pItem, pParameterType, pStateType, NULL, pState ); + g_lo_action_group_insert_stateful( pActionGroup, aCommand, pItem->mnId, pParameterType, pStateType, NULL, pState ); } else { // Item is not special, so insert a stateless action. - g_lo_action_group_insert( pActionGroup, aCommand, pItem ); + g_lo_action_group_insert( pActionGroup, aCommand, pItem->mnId ); } } @@ -555,6 +555,36 @@ void GtkSalMenu::GetSystemMenuData( SystemMenuData* pData ) { } +GtkSalMenu* GtkSalMenu::GetMenuForItemCommand( gchar* aCommand ) +{ + GtkSalMenu* pMenu = NULL; + + for ( sal_uInt16 nPos = 0; nPos < maItems.size(); nPos++ ) + { + GtkSalMenuItem *pSalItem = maItems[ nPos ]; + + String aItemCommand = mpVCLMenu->GetItemCommand( pSalItem->mnId ); + + gchar* aItemCommandStr = (gchar*) rtl::OUStringToOString( aItemCommand, RTL_TEXTENCODING_UTF8 ).getStr(); + + if ( g_strcmp0( aItemCommandStr, aCommand ) == 0 ) + { + pMenu = this; + break; + } + else + { + if ( pSalItem->mpSubMenu != NULL ) + pMenu = pSalItem->mpSubMenu->GetMenuForItemCommand( aCommand ); + + if ( pMenu != NULL ) + break; + } + } + + return pMenu; +} + void GtkSalMenu::Freeze() { } -- cgit v1.2.3