Browse Source

Two or more menu actions can now have the same keybinding

merge-requests/409/head
eidheim 4 years ago
parent
commit
53809dc93e
  1. 34
      src/menu.cpp
  2. 1
      src/menu.hpp
  3. 2
      src/source.cpp
  4. 14
      src/window.cpp

34
src/menu.cpp

@ -1,5 +1,6 @@
#include "menu.hpp" #include "menu.hpp"
#include "config.hpp" #include "config.hpp"
#include "terminal.hpp"
#include <iostream> #include <iostream>
#include <string> #include <string>
@ -578,14 +579,33 @@ void Menu::add_action(const std::string &name, const std::function<void()> &acti
void Menu::set_keys() { void Menu::set_keys() {
auto application = Glib::RefPtr<Gtk::Application>::cast_dynamic(Gtk::Application::get_default()); auto application = Glib::RefPtr<Gtk::Application>::cast_dynamic(Gtk::Application::get_default());
for(auto &key : Config::get().menu.keys) { accelerators_with_multiple_actions.clear();
if(actions.find(key.first) != actions.end()) {
if(!key.second.empty()) for(auto &action_and_key : Config::get().menu.keys) {
application->set_accel_for_action("app." + key.first, key.second); auto it = actions.find(action_and_key.first);
if(it != actions.end()) {
if(!action_and_key.second.empty()) {
application->set_accel_for_action("app." + action_and_key.first, action_and_key.second);
guint key = 0;
GdkModifierType modifier = static_cast<GdkModifierType>(0);
gtk_accelerator_parse(action_and_key.second.c_str(), &key, &modifier);
if(key == 0 && modifier == 0)
Terminal::get().async_print("\e[31mError\e[m: could not parse key string \"" + action_and_key.second + "\" for action " + action_and_key.first + "\n", true);
else
accelerators_with_multiple_actions[std::make_pair(key, modifier)].emplace_back(it->second);
}
else else
application->unset_accels_for_action("app." + key.first); application->unset_accels_for_action("app." + action_and_key.first);
} }
} }
for(auto it = accelerators_with_multiple_actions.begin(); it != accelerators_with_multiple_actions.end();) {
if(it->second.size() < 2)
it = accelerators_with_multiple_actions.erase(it);
else
++it;
}
} }
void Menu::build() { void Menu::build() {
@ -602,7 +622,7 @@ void Menu::build() {
ptr = Glib::RefPtr<Gio::Menu>::cast_dynamic(object); ptr = Glib::RefPtr<Gio::Menu>::cast_dynamic(object);
right_click_selected_menu = std::make_unique<Gtk::Menu>(ptr); right_click_selected_menu = std::make_unique<Gtk::Menu>(ptr);
} }
catch(const Glib::Error &ex) { catch(const Glib::Error &e) {
std::cerr << "building menu failed: " << ex.what(); std::cerr << "building menu failed: " << e.what();
} }
} }

1
src/menu.hpp

@ -15,6 +15,7 @@ public:
void add_action(const std::string &name, const std::function<void()> &action); void add_action(const std::string &name, const std::function<void()> &action);
std::unordered_map<std::string, Glib::RefPtr<Gio::SimpleAction>> actions; std::unordered_map<std::string, Glib::RefPtr<Gio::SimpleAction>> actions;
std::map<std::pair<guint, GdkModifierType>, std::vector<Glib::RefPtr<Gio::SimpleAction>>> accelerators_with_multiple_actions;
void set_keys(); void set_keys();
void build(); void build();

2
src/source.cpp

@ -2597,7 +2597,7 @@ bool Source::View::on_key_press_event(GdkEventKey *event) {
guint keyval_without_state; guint keyval_without_state;
gdk_keymap_translate_keyboard_state(gdk_keymap_get_default(), event->hardware_keycode, (GdkModifierType)0, 0, &keyval_without_state, nullptr, nullptr, nullptr); gdk_keymap_translate_keyboard_state(gdk_keymap_get_default(), event->hardware_keycode, (GdkModifierType)0, 0, &keyval_without_state, nullptr, nullptr, nullptr);
for(auto &snippet : *snippets) { for(auto &snippet : *snippets) {
if((snippet.key == event->keyval || snippet.key == keyval_without_state) && (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK | GDK_META_MASK)) == snippet.modifier) { if(snippet.key == keyval_without_state && (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK | GDK_META_MASK)) == snippet.modifier) {
insert_snippet(get_buffer()->get_insert()->get_iter(), snippet.body); insert_snippet(get_buffer()->get_insert()->get_iter(), snippet.body);
return true; return true;
} }

14
src/window.cpp

@ -1939,7 +1939,7 @@ bool Window::on_key_press_event(GdkEventKey *event) {
guint keyval_without_state; guint keyval_without_state;
gdk_keymap_translate_keyboard_state(gdk_keymap_get_default(), event->hardware_keycode, (GdkModifierType)0, 0, &keyval_without_state, nullptr, nullptr, nullptr); gdk_keymap_translate_keyboard_state(gdk_keymap_get_default(), event->hardware_keycode, (GdkModifierType)0, 0, &keyval_without_state, nullptr, nullptr, nullptr);
for(auto &command : Commands::get().commands) { for(auto &command : Commands::get().commands) {
if((command.key == event->keyval || command.key == keyval_without_state) && (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK | GDK_META_MASK)) == command.modifier) { if(command.key == keyval_without_state && (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK | GDK_META_MASK)) == command.modifier) {
auto view = Notebook::get().get_current_view(); auto view = Notebook::get().get_current_view();
auto view_folder = Project::get_preferably_view_folder(); auto view_folder = Project::get_preferably_view_folder();
auto path = view ? view->file_path : view_folder; auto path = view ? view->file_path : view_folder;
@ -2021,9 +2021,8 @@ bool Window::on_key_press_event(GdkEventKey *event) {
} }
} }
if(event->keyval == GDK_KEY_Escape) { if(event->keyval == GDK_KEY_Escape)
EntryBox::get().hide(); EntryBox::get().hide();
}
#ifdef __APPLE__ //For Apple's Command-left, right, up, down keys #ifdef __APPLE__ //For Apple's Command-left, right, up, down keys
else if((event->state & GDK_META_MASK) > 0 && (event->state & GDK_MOD1_MASK) == 0) { else if((event->state & GDK_META_MASK) > 0 && (event->state & GDK_MOD1_MASK) == 0) {
if(event->keyval == GDK_KEY_Left || event->keyval == GDK_KEY_KP_Left) { if(event->keyval == GDK_KEY_Left || event->keyval == GDK_KEY_KP_Left) {
@ -2056,6 +2055,15 @@ bool Window::on_key_press_event(GdkEventKey *event) {
return true; return true;
} }
auto it = Menu::get().accelerators_with_multiple_actions.find(std::make_pair(keyval_without_state, static_cast<GdkModifierType>(event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK | GDK_META_MASK))));
if(it != Menu::get().accelerators_with_multiple_actions.end()) {
// Copy actions since accelerators_with_multiple_actions might change during activations
auto actions = it->second;
for(auto &action : actions)
action->activate();
return true;
}
return Gtk::ApplicationWindow::on_key_press_event(event); return Gtk::ApplicationWindow::on_key_press_event(event);
} }

Loading…
Cancel
Save