diff options
| author | William Hua <william.hua@canonical.com> | 2013-12-23 01:29:26 -0500 |
|---|---|---|
| committer | William Hua <william.hua@canonical.com> | 2013-12-23 01:29:26 -0500 |
| commit | 63f4ce233927d32175c85ddf43d193814487c121 (patch) | |
| tree | 82f0efdda20e3e63b9b35e8c69c6133c7e080171 /plugins | |
| parent | 8519172eb240d02f10c7c31fc85a1194363657e6 (diff) | |
Fix vector re-allocation crash.
(bzr r3608.4.4)
Diffstat (limited to 'plugins')
| -rw-r--r-- | plugins/unityshell/src/GnomeKeyGrabber.cpp | 177 | ||||
| -rw-r--r-- | plugins/unityshell/src/GnomeKeyGrabber.h | 4 | ||||
| -rw-r--r-- | plugins/unityshell/src/GnomeKeyGrabberImpl.h | 52 |
3 files changed, 153 insertions, 80 deletions
diff --git a/plugins/unityshell/src/GnomeKeyGrabber.cpp b/plugins/unityshell/src/GnomeKeyGrabber.cpp index 52bc0dad8..b55252559 100644 --- a/plugins/unityshell/src/GnomeKeyGrabber.cpp +++ b/plugins/unityshell/src/GnomeKeyGrabber.cpp @@ -62,71 +62,123 @@ namespace testing const std::string DBUS_NAME = "com.canonical.Unity.Test.GnomeKeyGrabber"; } -GnomeKeyGrabber::Impl::Impl(GnomeKeyGrabber* grabber, CompScreen* screen, bool test_mode) - : grabber_(grabber) - , shell_server_(test_mode ? testing::DBUS_NAME : shell::DBUS_NAME) +bool GnomeKeyGrabber::Impl::BindingLess::operator() + (const CompAction::KeyBinding& first, + const CompAction::KeyBinding& second) const +{ + return first.keycode() < second.keycode() || + (first.keycode() == second.keycode() && + first.modifiers() < second.modifiers()); +} + +GnomeKeyGrabber::Impl::Info::Info(CompAction* action, + const CompAction* address) + : action_(action) + , address_(address) +{ +} + +GnomeKeyGrabber::Impl::Impl(CompScreen* screen, bool test_mode) + : test_mode_(test_mode) + , shell_server_(test_mode_ ? testing::DBUS_NAME : shell::DBUS_NAME) , screen_(screen) , current_action_id_(0) - , test_mode_(test_mode) { shell_server_.AddObjects(shell::INTROSPECTION_XML, shell::DBUS_OBJECT_PATH); shell_object_ = shell_server_.GetObject(shell::DBUS_INTERFACE); - shell_object_->SetMethodsCallsHandler(sigc::mem_fun(this, &Impl::onShellMethodCall)); + shell_object_->SetMethodsCallsHandler( + sigc::mem_fun(this, &Impl::onShellMethodCall)); } -GnomeKeyGrabber::Impl::~Impl() +unsigned int GnomeKeyGrabber::Impl::addAction(const CompAction& action, + bool addressable) { -} + bool resize(actions_.size() == actions_.capacity()); -unsigned int GnomeKeyGrabber::Impl::addAction(const CompAction& action) -{ current_action_id_++; actions_.push_back(action); - action_for_id_[current_action_id_] = &actions_.back(); - screen_->addAction(&actions_.back()); + CompAction& added(actions_.back()); + action_ids_.push_back(current_action_id_); + Info& info(info_by_action_id_[current_action_id_]); + + if (addressable) + { + action_ids_by_address_[&action] = current_action_id_; + info.address_ = &action; + } + + if (!resize) + { + action_ids_by_action_[&added] = current_action_id_; + info.action_ = &added; + } + else + { + action_ids_by_action_.clear(); + + for (unsigned int i(0); i < actions_.size(); i++) + { + action_ids_by_action_[&actions_[i]] = action_ids_[i]; + info_by_action_id_[action_ids_[i]].action_ = &actions_[i]; + } + } + + std::map<CompAction::KeyBinding, unsigned int>::iterator + i(grabs_by_binding_.find(added.key())); + + if (i == grabs_by_binding_.end()) + { + grabs_by_binding_[added.key()] = 0; + i = grabs_by_binding_.find(added.key()); + } + + if (i->second++ == 0) + screen_->addAction(&added); + return current_action_id_; } bool GnomeKeyGrabber::Impl::removeAction(const CompAction& action) { - bool removed(false); - - std::list<unsigned int> action_ids; - - for (std::map<unsigned int, CompAction*>::const_iterator i(action_for_id_.begin()); i != action_for_id_.end(); ++i) - if (*i->second == action) - action_ids.push_front(i->first); - - for (std::list<unsigned int>::const_iterator i(action_ids.begin()); i != action_ids.end(); ++i) - removed = removeAction(*i) || removed; + std::map<const CompAction*, unsigned int>::const_iterator + i(action_ids_by_address_.find(&action)); - return removed; + return i != action_ids_by_address_.end() && removeAction(i->second); } bool GnomeKeyGrabber::Impl::removeAction(unsigned int action_id) { - std::map<unsigned int, CompAction*>::iterator i(action_for_id_.find(action_id)); + std::map<unsigned int, Info>::iterator + i(info_by_action_id_.find(action_id)); - if (i != action_for_id_.end()) + if (i != info_by_action_id_.end()) { - CompAction* action = i->second; + CompAction* action(i->second.action_); + const CompAction* address(i->second.address_); - screen_->removeAction(action); - action_for_id_.erase(i); + if (--grabs_by_binding_[action->key()] == 0) + screen->removeAction(action); - for (CompAction::Vector::iterator j(actions_.begin()); j != actions_.end(); ++j) + std::vector<unsigned int>::iterator + j(std::find(action_ids_.begin(), action_ids_.end(), action_id)); + + if (j != action_ids_.end()) { - if (&*j == action) { - actions_.erase(j); - return true; - } + actions_.erase(actions_.begin() + (j - action_ids_.begin())); + action_ids_.erase(j); } + + action_ids_by_action_.erase(action); + action_ids_by_address_.erase(address); + info_by_action_id_.erase(i); + return true; } return false; } -GVariant* GnomeKeyGrabber::Impl::onShellMethodCall(const std::string& method, GVariant* parameters) +GVariant* GnomeKeyGrabber::Impl::onShellMethodCall(const std::string& method, + GVariant* parameters) { LOG_DEBUG(logger) << "Called method '" << method << "'"; @@ -144,7 +196,8 @@ GVariant* GnomeKeyGrabber::Impl::onShellMethodCall(const std::string& method, GV g_variant_get(parameters, "(a(su))", &iterator); while (g_variant_iter_next(iterator, "(&su)", &accelerator, &flags)) - g_variant_builder_add(&builder, "u", grabAccelerator(accelerator, flags)); + g_variant_builder_add(&builder, "u", grabAccelerator(accelerator, + flags)); g_variant_iter_free(iterator); variant = g_variant_builder_end(&builder); @@ -186,55 +239,50 @@ GVariant* GnomeKeyGrabber::Impl::onShellMethodCall(const std::string& method, GV return nullptr; } -unsigned int GnomeKeyGrabber::Impl::grabAccelerator(const char *accelerator, unsigned int flags) +unsigned int GnomeKeyGrabber::Impl::grabAccelerator(const char* accelerator, + unsigned int flags) { CompAction action; action.keyFromString(accelerator); if (!isActionPostponed(action)) { - action.setInitiate(boost::bind(&GnomeKeyGrabber::Impl::actionInitiated, this, _1, _2, _3)); action.setState(CompAction::StateInitKey); + action.setInitiate(boost::bind(&GnomeKeyGrabber::Impl::actionInitiated, + this, _1, _2, _3)); } else { - action.setTerminate(boost::bind(&GnomeKeyGrabber::Impl::actionTerminated, this, _1, _2, _3)); action.setState(CompAction::StateTermKey); + action.setTerminate(boost::bind(&GnomeKeyGrabber::Impl::actionTerminated, + this, _1, _2, _3)); } - return addAction(action); + return addAction(action, false); } -void GnomeKeyGrabber::Impl::activateAction(const CompAction* action, unsigned int device) const +void GnomeKeyGrabber::Impl::activateAction(const CompAction* action, + unsigned int device) const { - unsigned int action_id(-1); - unsigned int closest_action_id(-1); - - for (std::map<unsigned int, CompAction*>::const_iterator i(action_for_id_.begin()); i != action_for_id_.end(); ++i) - { - if (i->second == action) - { - action_id = i->first; - break; - } - - if (*i->second == *action && (closest_action_id < 0 || i->first < closest_action_id)) - closest_action_id = i->first; - } + std::map<const CompAction*, unsigned int>::const_iterator + i(action_ids_by_action_.find(action)); - if (action_id >= 0) - shell_object_->EmitSignal("AcceleratorActivated", g_variant_new("(uu)", action_id, device)); - else if (closest_action_id >= 0) - shell_object_->EmitSignal("AcceleratorActivated", g_variant_new("(uu)", closest_action_id, device)); + if (i != action_ids_by_action_.end()) + shell_object_->EmitSignal("AcceleratorActivated", + g_variant_new("(uu)", i->second, device)); } -bool GnomeKeyGrabber::Impl::actionInitiated(CompAction* action, CompAction::State state, CompOption::Vector& options) const +bool GnomeKeyGrabber::Impl::actionInitiated(CompAction* action, + CompAction::State state, + CompOption::Vector& options) const { activateAction(action, 0); return true; } -bool GnomeKeyGrabber::Impl::actionTerminated(CompAction* action, CompAction::State state, CompOption::Vector& options) const +bool GnomeKeyGrabber::Impl::actionTerminated(CompAction* action, + CompAction::State state, + CompOption::Vector& options) const { if (state & CompAction::StateTermTapped) { @@ -245,20 +293,21 @@ bool GnomeKeyGrabber::Impl::actionTerminated(CompAction* action, CompAction::Sta return false; } -bool GnomeKeyGrabber::Impl::isActionPostponed(CompAction& action) +bool GnomeKeyGrabber::Impl::isActionPostponed(const CompAction& action) const { - return !action.key().keycode() || modHandler->keycodeToModifiers(action.key().keycode()); + int keycode(action.key().keycode()); + return keycode == 0 || modHandler->keycodeToModifiers(keycode) != 0; } // Public implementation GnomeKeyGrabber::GnomeKeyGrabber(CompScreen* screen) - : impl_(new GnomeKeyGrabber::Impl(this, screen)) + : impl_(new Impl(screen)) { } -GnomeKeyGrabber::GnomeKeyGrabber(CompScreen* screen, GnomeKeyGrabber::TestMode const& tm) - : impl_(new GnomeKeyGrabber::Impl(this, screen, true)) +GnomeKeyGrabber::GnomeKeyGrabber(CompScreen* screen, const TestMode& dummy) + : impl_(new Impl(screen, true)) { } diff --git a/plugins/unityshell/src/GnomeKeyGrabber.h b/plugins/unityshell/src/GnomeKeyGrabber.h index a91771c59..1b71a442e 100644 --- a/plugins/unityshell/src/GnomeKeyGrabber.h +++ b/plugins/unityshell/src/GnomeKeyGrabber.h @@ -32,7 +32,7 @@ class GnomeKeyGrabber public: explicit GnomeKeyGrabber(CompScreen* screen); - ~GnomeKeyGrabber(); + virtual ~GnomeKeyGrabber(); CompAction::Vector& getActions(); void addAction(const CompAction& action); @@ -43,7 +43,7 @@ public: protected: struct TestMode {}; - GnomeKeyGrabber(CompScreen* screen, TestMode const&); + GnomeKeyGrabber(CompScreen* screen, const TestMode& dummy); private: diff --git a/plugins/unityshell/src/GnomeKeyGrabberImpl.h b/plugins/unityshell/src/GnomeKeyGrabberImpl.h index 1dfb8a671..15c63e72c 100644 --- a/plugins/unityshell/src/GnomeKeyGrabberImpl.h +++ b/plugins/unityshell/src/GnomeKeyGrabberImpl.h @@ -32,32 +32,56 @@ namespace grabber struct GnomeKeyGrabber::Impl { - Impl(GnomeKeyGrabber* parent, CompScreen* screen, bool test_mode = false); - ~Impl(); + struct Info + { + CompAction* action_; + const CompAction* address_; - unsigned int addAction(const CompAction& action); - bool removeAction(const CompAction& action); - bool removeAction(unsigned int action_id); + explicit Info(CompAction* action = nullptr, + const CompAction* address = nullptr); + }; - GVariant* onShellMethodCall(const std::string& method, GVariant* parameters); - unsigned int grabAccelerator(const char *accelerator, unsigned int flags); - void activateAction(const CompAction* action, unsigned int device) const; + class BindingLess + { + public: - bool actionInitiated(CompAction* action, CompAction::State state, CompOption::Vector& options) const; - bool actionTerminated(CompAction* action, CompAction::State state, CompOption::Vector& options) const; + bool operator()(const CompAction::KeyBinding& first, + const CompAction::KeyBinding& second) const; + }; - bool isActionPostponed(CompAction& action); + bool test_mode_; - GnomeKeyGrabber* grabber_; glib::DBusServer shell_server_; glib::DBusObject::Ptr shell_object_; CompScreen* screen_; CompAction::Vector actions_; + std::vector<unsigned int> action_ids_; unsigned int current_action_id_; - std::map<unsigned int, CompAction*> action_for_id_; - bool test_mode_; + std::map<unsigned int, Info> info_by_action_id_; + std::map<const CompAction*, unsigned int> action_ids_by_action_; + std::map<const CompAction*, unsigned int> action_ids_by_address_; + std::map<CompAction::KeyBinding, unsigned int, BindingLess> grabs_by_binding_; + + explicit Impl(CompScreen* screen, bool test_mode = false); + + unsigned int addAction(const CompAction& action, bool addressable = true); + bool removeAction(const CompAction& action); + bool removeAction(unsigned int action_id); + + GVariant* onShellMethodCall(const std::string& method, GVariant* parameters); + unsigned int grabAccelerator(const char* accelerator, unsigned int flags); + void activateAction(const CompAction* action, unsigned int device) const; + + bool actionInitiated(CompAction* action, + CompAction::State state, + CompOption::Vector& options) const; + bool actionTerminated(CompAction* action, + CompAction::State state, + CompOption::Vector& options) const; + + bool isActionPostponed(const CompAction& action) const; }; } // namespace grabber |
