diff -Nru hud-13.10.1+14.04.20140425/data/hud.conf.in hud-14.04+14.04.20140604/data/hud.conf.in --- hud-13.10.1+14.04.20140425/data/hud.conf.in 2014-04-25 08:48:23.000000000 +0000 +++ hud-14.04+14.04.20140604/data/hud.conf.in 2014-06-04 14:04:03.000000000 +0000 @@ -1,22 +1,10 @@ description "Unity HUD" -pre-start script - if [ -z $DBUS_SESSION_BUS_ADDRESS ]; then - echo "Working around missing DBUS_SESSION_BUS_ADDRESS variable" - printf "DuplicateSignature\0DBusSessionAddressNotSet" | /usr/share/apport/recoverable_problem -p `pidof -s -o 1 init` - . "${HOME}/.cache/upstart/dbus-session" - initctl set-env "DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS" - fi -end script - # Currently started by the dbus service file # start on dbus-activation com.canonical.hud stop on desktop-end start on started dbus and ((xsession SESSION=ubuntu-touch) or (xsession SESSION=ubuntu-touch-surfaceflinger) or (xsession SESSION=ubuntu)) -env HUD_SERVICE_TIMEOUT=0 -export HUD_SERVICE_TIMEOUT - pre-start script if [ -z $DBUS_SESSION_BUS_ADDRESS ]; then echo "Working around missing DBUS_SESSION_BUS_ADDRESS variable" diff -Nru hud-13.10.1+14.04.20140425/debian/changelog hud-14.04+14.04.20140604/debian/changelog --- hud-13.10.1+14.04.20140425/debian/changelog 2014-06-11 16:32:12.000000000 +0000 +++ hud-14.04+14.04.20140604/debian/changelog 2014-06-11 16:32:12.000000000 +0000 @@ -1,3 +1,14 @@ +hud (14.04+14.04.20140604-0ubuntu1) trusty; urgency=medium + + [ Pete Woods ] + * Resolve crasher in previous attempted SRU. (LP: #1298656) + - Fix order of menu traversal. + - Add timeout to legacy HUD queries. + - Improve legacy menu safety valve trigger. + - Remove duplicate entries in upstart job. + + -- Ubuntu daily release Wed, 04 Jun 2014 14:04:12 +0000 + hud (13.10.1+14.04.20140425-0ubuntu1) trusty; urgency=low [ Pete Woods ] diff -Nru hud-13.10.1+14.04.20140425/libqtgmenu/internal/QtGActionGroup.cpp hud-14.04+14.04.20140604/libqtgmenu/internal/QtGActionGroup.cpp --- hud-13.10.1+14.04.20140425/libqtgmenu/internal/QtGActionGroup.cpp 2014-04-25 08:48:33.000000000 +0000 +++ hud-14.04+14.04.20140604/libqtgmenu/internal/QtGActionGroup.cpp 2014-06-04 14:04:03.000000000 +0000 @@ -126,13 +126,11 @@ bool enabled = G_ACTION_GROUP_GET_IFACE( m_action_group.data() ) ->get_action_enabled( m_action_group.data(), action_name ); - if( !enabled ) - emit ActionEnabled( FullName(m_action_prefix, action_name), enabled ); + emit ActionEnabled( FullName(m_action_prefix, action_name), enabled ); const GVariantType* type = g_action_group_get_action_parameter_type( m_action_group.data(), action_name ); - if( type != nullptr ) - emit ActionParameterized( FullName(m_action_prefix, action_name), type != nullptr ); + emit ActionParameterized( FullName(m_action_prefix, action_name), type != nullptr ); } g_strfreev( actions_list ); diff -Nru hud-13.10.1+14.04.20140425/libqtgmenu/internal/QtGMenuModel.cpp hud-14.04+14.04.20140604/libqtgmenu/internal/QtGMenuModel.cpp --- hud-13.10.1+14.04.20140425/libqtgmenu/internal/QtGMenuModel.cpp 2014-04-25 08:48:33.000000000 +0000 +++ hud-14.04+14.04.20140604/libqtgmenu/internal/QtGMenuModel.cpp 2014-06-04 14:04:03.000000000 +0000 @@ -173,7 +173,10 @@ auto action_it = m_actions.find( action_name ); if( action_it != end( m_actions ) ) { - action_it->second.second->setEnabled( enabled ); + for( auto& action : action_it->second ) + { + action->setEnabled( enabled ); + } } } @@ -182,7 +185,10 @@ auto action_it = m_actions.find( action_name ); if( action_it != end( m_actions ) ) { - action_it->second.second->setProperty( c_property_isParameterized, parameterized ); + for( auto& action : action_it->second ) + { + action->setProperty( c_property_isParameterized, parameterized ); + } } } @@ -238,7 +244,6 @@ void QtGMenuModel::ChangeMenuItems( const int index, const int added, const int removed ) { const int n_items = g_menu_model_get_n_items( m_model.data() ); - bool invalid_arguments = false; if( index < 0 || added < 0 || removed < 0 || index + added > n_items || index + removed > m_size ) { @@ -255,7 +260,7 @@ if( index < m_menu->actions().size() ) { QAction* at_action = m_menu->actions().at( index ); - ActionRemoved( at_action->property( c_property_actionName ).toString() ); + ActionRemoved( at_action->property( c_property_actionName ).toString(), at_action ); m_menu->removeAction( at_action ); } } @@ -282,8 +287,8 @@ // now process added items if( added > 0 ) { - // update m_children - for( int i = index; i < ( index + added ); ++i ) + // update m_children (start from the end and work backwards as not to overlap items as we shift them up) + for( int i = m_size - 1; i >= index; --i ) { // shift 'added' items up from their current index to ( index + added ) if( m_children.contains( i ) ) @@ -333,10 +338,6 @@ // update external menu UpdateExtQMenu(); - if( m_link_type == LinkType::Section && m_parent ) - { - m_parent->UpdateExtQMenu(); - } // now tell the outside world that items have changed emit MenuItemsChanged( this, index, removed, added ); @@ -522,6 +523,12 @@ m_ext_menu->removeAction( last_action ); } } + + // if this is a section within a parent menu, we need to update the parent menu as well + if( m_link_type == LinkType::Section && m_parent ) + { + m_parent->UpdateExtQMenu(); + } } void QtGMenuModel::ActionAdded( const QString& name, QAction* action ) @@ -533,36 +540,44 @@ } else { - // check if this action is already in our map + // check if the action name is already in our map if( m_actions.find( name ) != m_actions.end() ) { - // increment the reference count for this action - ++m_actions[name].first; + // add the QAction pointer to the list of actions under this name + m_actions[name].push_back( action ); } else { // otherwise insert the new action into the map - m_actions.insert( std::make_pair( name, std::make_pair( 1, action ) ) ); + m_actions.insert( std::make_pair( name, std::vector< QAction* >{ action } ) ); } } } -void QtGMenuModel::ActionRemoved( const QString& name ) +void QtGMenuModel::ActionRemoved( const QString& name, QAction* action ) { // remove action from top menu's m_actions if( m_parent ) { - m_parent->ActionRemoved( name ); + m_parent->ActionRemoved( name, action ); } else { // check if this action is actually in our map if( m_actions.find( name ) != m_actions.end() ) { - // decrement the reference count for this action - if( --m_actions[name].first == 0 ) + // remove the QAction pointer from the list of actions under this name + auto& actionList = m_actions[name]; + auto actionIt = std::find( actionList.begin(), actionList.end(), action ); + + if( actionIt != actionList.end()) + { + actionList.erase( actionIt ); + } + + // if there are no more references to this action, remove it from the map + if( actionList.size() == 0 ) { - // if there are no more references to this action, remove it from the map m_actions.erase( name ); } } diff -Nru hud-13.10.1+14.04.20140425/libqtgmenu/internal/QtGMenuModel.h hud-14.04+14.04.20140604/libqtgmenu/internal/QtGMenuModel.h --- hud-13.10.1+14.04.20140425/libqtgmenu/internal/QtGMenuModel.h 2014-04-25 08:48:33.000000000 +0000 +++ hud-14.04+14.04.20140604/libqtgmenu/internal/QtGMenuModel.h 2014-06-04 14:04:03.000000000 +0000 @@ -95,7 +95,7 @@ void UpdateExtQMenu(); void ActionAdded( const QString& name, QAction* action ); - void ActionRemoved( const QString& name ); + void ActionRemoved( const QString& name, QAction* action ); void ReportRecoverableError(const int index, const int added, const int removed); @@ -118,7 +118,7 @@ QMap m_action_paths; // a map of QActions indexed by their name and stored with a reference count - std::map< QString, std::pair< int, QAction* > > m_actions; + std::map< QString, std::vector< QAction* > > m_actions; bool m_error_reported = false; }; diff -Nru hud-13.10.1+14.04.20140425/service/DBusMenuCollector.cpp hud-14.04+14.04.20140604/service/DBusMenuCollector.cpp --- hud-13.10.1+14.04.20140425/service/DBusMenuCollector.cpp 2014-04-25 08:48:23.000000000 +0000 +++ hud-14.04+14.04.20140604/service/DBusMenuCollector.cpp 2014-06-04 14:04:03.000000000 +0000 @@ -82,25 +82,18 @@ return !m_menuImporter.isNull(); } -inline uint qHash(const QStringList &key, uint seed) { - uint hash(0); - for (const QString &s : key) { - hash ^= qHash(s, seed); - } - return hash; -} - void DBusMenuCollector::openMenu(QMenu *menu, unsigned int &limit) { - if (!menu) { - return; - } - + --limit; if (limit == 0) { - QString error = "Hit DBusMenu safety valve for menu at " + m_service + QString error = "Hit DBusMenu safety valve opening menu at " + m_service + " " + m_path.path(); throw std::logic_error(error.toStdString()); } + if (!menu) { + return; + } + menu->aboutToShow(); for (int i(0); m_menuImporter && i < menu->actions().size(); ++i) { @@ -114,15 +107,15 @@ QMenu *child(action->menu()); if (child) { - --limit; openMenu(child, limit); } } } void DBusMenuCollector::hideMenu(QMenu *menu, unsigned int &limit) { + --limit; if (limit == 0) { - QString error = "Hit DBusMenu safety valve for menu at " + m_service + QString error = "Hit DBusMenu safety valve closing menu at " + m_service + " " + m_path.path(); throw std::logic_error(error.toStdString()); } @@ -131,7 +124,6 @@ QAction *action = menu->actions().at(i); QMenu *child(action->menu()); if (child) { - --limit; hideMenu(child, limit); } } diff -Nru hud-13.10.1+14.04.20140425/service/HudServiceImpl.cpp hud-14.04+14.04.20140604/service/HudServiceImpl.cpp --- hud-13.10.1+14.04.20140425/service/HudServiceImpl.cpp 2014-04-25 08:48:23.000000000 +0000 +++ hud-14.04+14.04.20140604/service/HudServiceImpl.cpp 2014-06-04 14:04:03.000000000 +0000 @@ -104,13 +104,24 @@ QList &suggestions, QDBusVariant &querykey) { QString sender(messageSender()); - Query::Ptr query(m_legacyQueries[sender]); + QPair> entry(m_legacyQueries[sender]); + Query::Ptr query(entry.first); + QSharedPointer legacyTimeout(entry.second); if (query.isNull()) { query = createQuery(queryString, sender, Query::EmptyBehaviour::NO_SUGGESTIONS); - m_legacyQueries[sender] = query; + + legacyTimeout.reset(new QTimer()); + legacyTimeout->setInterval(2000); + legacyTimeout->setSingleShot(true); + connect(legacyTimeout.data(), SIGNAL(timeout()), this, + SLOT(legacyTimeout())); + + m_legacyQueries[sender] = qMakePair(query, legacyTimeout); } else { query->UpdateQuery(queryString); + legacyTimeout->stop(); + legacyTimeout->setProperty("sender", QVariant()); } // The legacy API only allows you to search the current application @@ -142,8 +153,13 @@ Q_UNUSED(timestamp); QString sender(messageSender()); - Query::Ptr query(m_legacyQueries.take(sender)); + QPair> entry(m_legacyQueries.take(sender)); + Query::Ptr query(entry.first); + QSharedPointer legacyTimeout(entry.second); if (!query.isNull()) { + legacyTimeout->stop(); + legacyTimeout->setProperty("sender", QVariant()); + query->ExecuteCommand(itemKey, timestamp); closeQuery(query->path()); } @@ -156,8 +172,32 @@ // We don't actually close legacy queries, or we'd be constructing // and destructing them during the search, due to the way that // Unity7 uses the API. - Query::Ptr query(m_legacyQueries[sender]); + QPair> entry(m_legacyQueries[sender]); + Query::Ptr query(entry.first); + QSharedPointer legacyTimeout(entry.second); if (!query.isNull()) { query->UpdateQuery(QString()); + legacyTimeout->start(); + legacyTimeout->setProperty("sender", sender); + } +} + +void HudServiceImpl::legacyTimeout() { + QObject *timer(sender()); + if (!timer) { + return; } + + QVariant from(timer->property("sender")); + if (from.isNull()) { + return; + } + + QString sender(from.toString()); + QPair> entry(m_legacyQueries.take(sender)); + Query::Ptr query(entry.first); + if (query) { + closeQuery(query->path()); + } + } diff -Nru hud-13.10.1+14.04.20140425/service/HudServiceImpl.h hud-14.04+14.04.20140604/service/HudServiceImpl.h --- hud-13.10.1+14.04.20140425/service/HudServiceImpl.h 2014-04-25 08:48:23.000000000 +0000 +++ hud-14.04+14.04.20140604/service/HudServiceImpl.h 2014-06-04 14:04:03.000000000 +0000 @@ -28,6 +28,7 @@ #include #include #include +#include class HudAdaptor; @@ -73,6 +74,9 @@ void CloseQuery(const QDBusVariant &querykey); +protected Q_SLOTS: + void legacyTimeout(); + protected: Query::Ptr createQuery(const QString &query, const QString &service, Query::EmptyBehaviour emptyBehaviour); @@ -85,7 +89,7 @@ QMap m_queries; - QMap m_legacyQueries; + QMap>> m_legacyQueries; QSharedPointer m_applicationList;