vcl/unx/gtk3/gtkinst.cxx | 273 +++++++++++++++++++++++------------------------ 1 file changed, 138 insertions(+), 135 deletions(-)
New commits: commit c118d90e13fff1b9404e179b61cd5919115a449c Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Wed Jul 7 16:03:04 2021 +0100 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Wed Jul 7 17:57:32 2021 +0200 gtk4: add get_item_id to MenuHelper and implement for the GMenuModel case Change-Id: I57da4d984f6a743043cd82c32edff35115fe94c6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118575 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caol...@redhat.com> diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx index cd4f8efc8e40..da39cf03f41a 100644 --- a/vcl/unx/gtk3/gtkinst.cxx +++ b/vcl/unx/gtk3/gtkinst.cxx @@ -5248,6 +5248,30 @@ public: #endif } + OString get_item_id(int pos) const + { +#if !GTK_CHECK_VERSION(4, 0, 0) + GList* pChildren = gtk_container_get_children(GTK_CONTAINER(m_pMenu)); + gpointer pMenuItem = g_list_nth_data(pChildren, pos); + OString id = ::get_buildable_id(GTK_BUILDABLE(pMenuItem)); + g_list_free(pChildren); + return id; +#else + OString sTarget; + if (GMenuModel* pMenuModel = gtk_popover_menu_get_menu_model(m_pMenu)) + { + auto aSectionAndPos = get_section_and_pos_for(pMenuModel, pos); + char *id; + if (g_menu_model_get_item_attribute(aSectionAndPos.first, aSectionAndPos.second, "target", "s", &id)) + { + sTarget = OString(id); + g_free(id); + } + } + return sTarget; +#endif + } + void clear_items() { #if !GTK_CHECK_VERSION(4, 0, 0) @@ -10486,15 +10510,7 @@ public: virtual OString get_id(int pos) const override { -#if !GTK_CHECK_VERSION(4, 0, 0) - GList* pChildren = gtk_container_get_children(GTK_CONTAINER(m_pMenu)); - gpointer pMenuItem = g_list_nth_data(pChildren, pos); - OString id = ::get_buildable_id(GTK_BUILDABLE(pMenuItem)); - g_list_free(pChildren); - return id; -#else - return OString(); -#endif + return get_item_id(pos); } virtual int n_children() const override commit 857943a0e4e75f12ffe7b1dc9d91ef88fbdb75d6 Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Wed Jul 7 15:22:58 2021 +0100 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Wed Jul 7 17:57:17 2021 +0200 gtk4: move more GMenuModel/GtkPopoverMenu handling into MenuHelper Change-Id: I994a0c6aeb2bfabec01999e4722ac0f72a3f359e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118574 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caol...@redhat.com> diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx index c5bc9657f309..cd4f8efc8e40 100644 --- a/vcl/unx/gtk3/gtkinst.cxx +++ b/vcl/unx/gtk3/gtkinst.cxx @@ -4775,6 +4775,8 @@ protected: bool m_bTakeOwnership; private: + virtual void signal_item_activate(const OString& rIdent) = 0; + #if !GTK_CHECK_VERSION(4, 0, 0) static void collect(GtkWidget* pItem, gpointer widget) { @@ -4791,8 +4793,6 @@ private: SolarMutexGuard aGuard; pThis->signal_item_activate(::get_buildable_id(GTK_BUILDABLE(pItem))); } - - virtual void signal_item_activate(const OString& rIdent) = 0; #else static std::pair<GMenuModel*, int> find_id(GMenuModel* pMenuModel, const OString& rId) { @@ -4825,6 +4825,28 @@ private: return std::make_pair(nullptr, -1); } + + void clear_actions() + { + for (const auto& rAction : m_aActionEntries) + { + g_action_map_remove_action(G_ACTION_MAP(m_pActionGroup), rAction.name); + g_action_map_remove_action(G_ACTION_MAP(m_pHiddenActionGroup), rAction.name); + } + m_aActionEntries.clear(); + m_aInsertedActions.clear(); + m_aIdToAction.clear(); + } + + static void action_activated(GSimpleAction*, GVariant* pParameter, gpointer widget) + { + gsize nLength(0); + const gchar* pStr = g_variant_get_string(pParameter, &nLength); + OString aStr(pStr, nLength); + MenuHelper* pThis = static_cast<MenuHelper*>(widget); + SolarMutexGuard aGuard; + pThis->signal_item_activate(aStr); + } #endif public: @@ -4907,11 +4929,75 @@ public: } #endif -#if !GTK_CHECK_VERSION(4, 0, 0) - void insert_item(int pos, std::u16string_view rId, const OUString& rStr, +#if GTK_CHECK_VERSION(4, 0, 0) + void process_menu_model(GMenuModel* pMenuModel) + { + for (int i = 0, nCount = g_menu_model_get_n_items(pMenuModel); i < nCount; ++i) + { + OString sAction, sTarget; + char *id; + if (g_menu_model_get_item_attribute(pMenuModel, i, "action", "s", &id)) + { + assert(OString(id).startsWith("menu.")); + + sAction = OString(id + 5); + + auto res = m_aInsertedActions.insert(sAction); + if (res.second) + { + // the const char* arg isn't copied by anything so it must continue to exist for the life time of + // the action group + if (sAction.startsWith("radio.")) + m_aActionEntries.push_back({res.first->getStr(), action_activated, "s", "'none'", nullptr, {}}); + else + m_aActionEntries.push_back({res.first->getStr(), action_activated, "s", nullptr, nullptr, {}}); + } + + g_free(id); + } + + if (g_menu_model_get_item_attribute(pMenuModel, i, "target", "s", &id)) + { + sTarget = OString(id); + g_free(id); + } + + m_aIdToAction[sTarget] = sAction; + + if (GMenuModel* pSectionModel = g_menu_model_get_item_link(pMenuModel, i, G_MENU_LINK_SECTION)) + process_menu_model(pSectionModel); + if (GMenuModel* pSubMenuModel = g_menu_model_get_item_link(pMenuModel, i, G_MENU_LINK_SUBMENU)) + process_menu_model(pSubMenuModel); + } + } + + // build an action group for the menu, "action" is the normal menu entry case + // the others are radiogroups + void update_action_group_from_popover_model() + { + clear_actions(); + + if (GMenuModel* pMenuModel = gtk_popover_menu_get_menu_model(m_pMenu)) + { + process_menu_model(pMenuModel); + } + + // move hidden entries to m_pHiddenActionGroup + g_action_map_add_action_entries(G_ACTION_MAP(m_pActionGroup), m_aActionEntries.data(), m_aActionEntries.size(), this); + for (const auto& id : m_aHiddenIds) + { + GAction* pAction = g_action_map_lookup_action(G_ACTION_MAP(m_pActionGroup), m_aIdToAction[id].getStr()); + g_action_map_add_action(G_ACTION_MAP(m_pHiddenActionGroup), pAction); + g_action_map_remove_action(G_ACTION_MAP(m_pActionGroup), m_aIdToAction[id].getStr()); + } + } +#endif + + void insert_item(int pos, const OUString& rId, const OUString& rStr, const OUString* pIconName, const VirtualDevice* pImageSurface, TriState eCheckRadioFalse) { +#if !GTK_CHECK_VERSION(4, 0, 0) GtkWidget* pImage = nullptr; if (pIconName && !pIconName->isEmpty()) { @@ -4951,8 +5037,29 @@ public: add_to_map(GTK_MENU_ITEM(pItem)); if (pos != -1) gtk_menu_reorder_child(m_pMenu, pItem, pos); - } +#else + (void)pIconName; (void)pImageSurface; + + if (GMenuModel* pMenuModel = gtk_popover_menu_get_menu_model(m_pMenu)) + { + auto aSectionAndPos = get_section_and_pos_for(pMenuModel, pos); + GMenu* pMenu = G_MENU(aSectionAndPos.first); + // action with a target value ... the action name and target value are separated by a double + // colon ... For example: "app.action::target" + OUString sActionAndTarget; + if (eCheckRadioFalse == TRISTATE_INDET) + sActionAndTarget = "menu.normal." + rId + "::" + rId; + else + sActionAndTarget = "menu.radio." + rId + "::" + rId; + g_menu_insert(pMenu, aSectionAndPos.second, MapToGtkAccelerator(rStr).getStr(), sActionAndTarget.toUtf8().getStr()); + + assert(eCheckRadioFalse == TRISTATE_INDET); // come back to this later + + // TODO not redo entire group + update_action_group_from_popover_model(); + } #endif + } void insert_separator(int pos, const OUString& rId) { @@ -9499,88 +9606,6 @@ private: #endif } -#if GTK_CHECK_VERSION(4, 0, 0) - void clear_actions() - { - for (const auto& rAction : m_aActionEntries) - { - g_action_map_remove_action(G_ACTION_MAP(m_pActionGroup), rAction.name); - g_action_map_remove_action(G_ACTION_MAP(m_pHiddenActionGroup), rAction.name); - } - m_aActionEntries.clear(); - m_aInsertedActions.clear(); - m_aIdToAction.clear(); - } -#endif - -#if GTK_CHECK_VERSION(4, 0, 0) - void process_menu_model(GMenuModel* pMenuModel) - { - for (int i = 0, nCount = g_menu_model_get_n_items(pMenuModel); i < nCount; ++i) - { - OString sAction, sTarget; - char *id; - if (g_menu_model_get_item_attribute(pMenuModel, i, "action", "s", &id)) - { - assert(OString(id).startsWith("menu.")); - - sAction = OString(id + 5); - - auto res = m_aInsertedActions.insert(sAction); - if (res.second) - { - // the const char* arg isn't copied by anything so it must continue to exist for the life time of - // the action group - if (sAction.startsWith("radio.")) - m_aActionEntries.push_back({res.first->getStr(), action_activated, "s", "'none'", nullptr, {}}); - else - m_aActionEntries.push_back({res.first->getStr(), action_activated, "s", nullptr, nullptr, {}}); - } - - g_free(id); - } - - if (g_menu_model_get_item_attribute(pMenuModel, i, "target", "s", &id)) - { - sTarget = OString(id); - g_free(id); - } - - m_aIdToAction[sTarget] = sAction; - - if (GMenuModel* pSectionModel = g_menu_model_get_item_link(pMenuModel, i, G_MENU_LINK_SECTION)) - process_menu_model(pSectionModel); - if (GMenuModel* pSubMenuModel = g_menu_model_get_item_link(pMenuModel, i, G_MENU_LINK_SUBMENU)) - process_menu_model(pSubMenuModel); - } - } - - // build an action group for the menu, "action" is the normal menu entry case - // the others are radiogroups - void update_action_group_from_popover_model() - { - clear_actions(); - - GtkPopover* pPopover = gtk_menu_button_get_popover(m_pMenuButton); - if (GMenuModel* pMenuModel = GTK_IS_POPOVER_MENU(pPopover) ? - gtk_popover_menu_get_menu_model(GTK_POPOVER_MENU(pPopover)) : - nullptr) - { - process_menu_model(pMenuModel); - } - - // move hidden entries to m_pHiddenActionGroup - g_action_map_add_action_entries(G_ACTION_MAP(m_pActionGroup), m_aActionEntries.data(), m_aActionEntries.size(), this); - for (const auto& id : m_aHiddenIds) - { - GAction* pAction = g_action_map_lookup_action(G_ACTION_MAP(m_pActionGroup), m_aIdToAction[id].getStr()); - g_action_map_add_action(G_ACTION_MAP(m_pHiddenActionGroup), pAction); - g_action_map_remove_action(G_ACTION_MAP(m_pActionGroup), m_aIdToAction[id].getStr()); - } - } - -#endif - static void signalFlagsChanged(GtkToggleButton* pToggleButton, GtkStateFlags flags, gpointer widget) { GtkInstanceMenuButton* pThis = static_cast<GtkInstanceMenuButton*>(widget); @@ -9741,33 +9766,7 @@ public: virtual void insert_item(int pos, const OUString& rId, const OUString& rStr, const OUString* pIconName, VirtualDevice* pImageSurface, TriState eCheckRadioFalse) override { -#if !GTK_CHECK_VERSION(4, 0, 0) MenuHelper::insert_item(pos, rId, rStr, pIconName, pImageSurface, eCheckRadioFalse); -#else - (void)pIconName; (void)pImageSurface; - - GtkPopover* pPopover = gtk_menu_button_get_popover(m_pMenuButton); - if (GMenuModel* pMenuModel = GTK_IS_POPOVER_MENU(pPopover) ? - gtk_popover_menu_get_menu_model(GTK_POPOVER_MENU(pPopover)) : - nullptr) - { - auto aSectionAndPos = get_section_and_pos_for(pMenuModel, pos); - GMenu* pMenu = G_MENU(aSectionAndPos.first); - // action with a target value ... the action name and target value are separated by a double - // colon ... For example: "app.action::target" - OUString sActionAndTarget; - if (eCheckRadioFalse == TRISTATE_INDET) - sActionAndTarget = "menu.normal." + rId + "::" + rId; - else - sActionAndTarget = "menu.radio." + rId + "::" + rId; - g_menu_insert(pMenu, aSectionAndPos.second, MapToGtkAccelerator(rStr).getStr(), sActionAndTarget.toUtf8().getStr()); - - assert(eCheckRadioFalse == TRISTATE_INDET); // come back to this later - - // TODO not redo entire group - update_action_group_from_popover_model(); - } -#endif } virtual void insert_separator(int pos, const OUString& rId) override @@ -9824,22 +9823,10 @@ public: MenuHelper::set_item_visible(rIdent, bVisible); } -#if GTK_CHECK_VERSION(4, 0, 0) - static void action_activated(GSimpleAction*, GVariant* pParameter, gpointer widget) - { - gsize nLength; - const gchar* pStr = g_variant_get_string(pParameter, &nLength); - OString aStr(pStr, nLength); - GtkInstanceMenuButton* pThis = static_cast<GtkInstanceMenuButton*>(widget); - SolarMutexGuard aGuard; - pThis->signal_selected(aStr); - } -#else virtual void signal_item_activate(const OString& rIdent) override { signal_selected(rIdent); } -#endif virtual void set_popover(weld::Widget* pPopover) override { @@ -10224,13 +10211,13 @@ protected: #endif private: -#if !GTK_CHECK_VERSION(4, 0, 0) virtual void signal_item_activate(const OString& rIdent) override { m_sActivated = rIdent; weld::Menu::signal_activate(m_sActivated); } +#if !GTK_CHECK_VERSION(4, 0, 0) void clear_extras() { if (m_aExtraItems.empty()) _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits