[Libreoffice-commits] core.git: Branch 'libreoffice-7-1' - vcl/inc vcl/unx

Caolán McNamara (via logerrit) logerrit at kemper.freedesktop.org
Tue Dec 1 15:17:43 UTC 2020


 vcl/inc/unx/gtk/gtksalmenu.hxx  |    6 +
 vcl/unx/gtk3/gtk3gtksalmenu.cxx |  161 ++++++++++++++++++++++++++++++++--------
 2 files changed, 137 insertions(+), 30 deletions(-)

New commits:
commit 8d20a638c6a25555f2835966fa322f7ddcf9e92e
Author:     Caolán McNamara <caolanm at redhat.com>
AuthorDate: Tue Dec 1 12:05:31 2020 +0000
Commit:     Caolán McNamara <caolanm at redhat.com>
CommitDate: Tue Dec 1 16:17:00 2020 +0100

    tdf#132350 gtk: implement extra update button in menubar
    
    Change-Id: I00c91c3b0ee1fd2ebfb3662bae2caf79962654f0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/106943
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx
index d4857fe7e87a..8af690d20a9d 100644
--- a/vcl/inc/unx/gtk/gtksalmenu.hxx
+++ b/vcl/inc/unx/gtk/gtksalmenu.hxx
@@ -33,6 +33,7 @@ class GtkSalMenu : public SalMenu
 {
 private:
     std::vector< GtkSalMenuItem* >  maItems;
+    std::vector<std::pair<sal_uInt16, GtkWidget*>> maExtraButtons;
     Idle                            maUpdateMenuBarIdle;
 
     bool                            mbInActivateCallback;
@@ -63,6 +64,8 @@ private:
 
     DECL_LINK(MenuBarHierarchyChangeHandler, Timer*, void);
 
+    static GtkWidget* AddButton(GtkWidget *pImage);
+
 public:
     GtkSalMenu( bool bMenuBar );
     virtual ~GtkSalMenu() override;
@@ -127,6 +130,9 @@ public:
 
     virtual bool ShowNativePopupMenu(FloatingWindow * pWin, const tools::Rectangle& rRect, FloatWinPopupFlags nFlags) override;
     virtual void ShowCloseButton(bool bShow) override;
+    virtual bool AddMenuBarButton( const SalMenuButtonItem& rNewItem ) override;
+    virtual void RemoveMenuBarButton( sal_uInt16 nId ) override;
+    virtual tools::Rectangle GetMenuBarButtonRectPixel( sal_uInt16 i_nItemId, SalFrame* i_pReferenceFrame ) override;
     virtual bool CanGetFocus() const override;
     virtual bool TakeFocus() override;
     virtual int GetMenuBarHeight() const override;
diff --git a/vcl/unx/gtk3/gtk3gtksalmenu.cxx b/vcl/unx/gtk3/gtk3gtksalmenu.cxx
index 72ad6e40d6bd..bd15de7de848 100644
--- a/vcl/unx/gtk3/gtk3gtksalmenu.cxx
+++ b/vcl/unx/gtk3/gtk3gtksalmenu.cxx
@@ -652,6 +652,28 @@ static void CloseMenuBar(GtkWidget *, gpointer pMenu)
     Application::PostUserEvent(static_cast<MenuBar*>(pMenu)->GetCloseButtonClickHdl());
 }
 
+GtkWidget* GtkSalMenu::AddButton(GtkWidget *pImage)
+{
+    GtkWidget* pButton = gtk_button_new();
+
+    gtk_button_set_relief(GTK_BUTTON(pButton), GTK_RELIEF_NONE);
+    gtk_button_set_focus_on_click(GTK_BUTTON(pButton), false);
+    gtk_widget_set_can_focus(pButton, false);
+
+    GtkStyleContext *pButtonContext = gtk_widget_get_style_context(GTK_WIDGET(pButton));
+
+    gtk_style_context_add_class(pButtonContext, "flat");
+    gtk_style_context_add_class(pButtonContext, "small-button");
+
+    gtk_widget_show(pImage);
+
+    gtk_widget_set_valign(pButton, GTK_ALIGN_CENTER);
+
+    gtk_container_add(GTK_CONTAINER(pButton), pImage);
+    gtk_widget_show_all(pButton);
+    return pButton;
+}
+
 void GtkSalMenu::ShowCloseButton(bool bShow)
 {
     assert(mbMenuBar);
@@ -668,35 +690,124 @@ void GtkSalMenu::ShowCloseButton(bool bShow)
         return;
     }
 
-    MenuBar *pVclMenuBar = static_cast<MenuBar*>(mpVCLMenu.get());
-    mpCloseButton = gtk_button_new();
-    gtk_widget_set_margin_start(mpCloseButton, 8);
+    if (mpCloseButton)
+        return;
+
+    GIcon* pIcon = g_themed_icon_new_with_default_fallbacks("window-close-symbolic");
+    GtkWidget* pImage = gtk_image_new_from_gicon(pIcon, GTK_ICON_SIZE_MENU);
+    g_object_unref(pIcon);
+
+    mpCloseButton = AddButton(pImage);
+
     gtk_widget_set_margin_end(mpCloseButton, 8);
+
+    OUString sToolTip(VclResId(SV_HELPTEXT_CLOSEDOCUMENT));
+    gtk_widget_set_tooltip_text(mpCloseButton, sToolTip.toUtf8().getStr());
+
+    MenuBar *pVclMenuBar = static_cast<MenuBar*>(mpVCLMenu.get());
     g_signal_connect(mpCloseButton, "clicked", G_CALLBACK(CloseMenuBar), pVclMenuBar);
 
-    gtk_button_set_relief(GTK_BUTTON(mpCloseButton), GTK_RELIEF_NONE);
-    gtk_button_set_focus_on_click(GTK_BUTTON(mpCloseButton), false);
-    gtk_widget_set_can_focus(mpCloseButton, false);
+    gtk_grid_attach(GTK_GRID(mpMenuBarContainerWidget), mpCloseButton, 1, 0, 1, 1);
+}
 
-    GtkStyleContext *pButtonContext = gtk_widget_get_style_context(GTK_WIDGET(mpCloseButton));
+namespace
+{
+    void DestroyMemoryStream(gpointer data)
+    {
+        SvMemoryStream* pMemStm = static_cast<SvMemoryStream*>(data);
+        delete pMemStm;
+    }
+}
 
-    gtk_style_context_add_class(pButtonContext, "flat");
-    gtk_style_context_add_class(pButtonContext, "small-button");
+static void MenuButtonClicked(GtkWidget* pWidget, gpointer pMenu)
+{
+    const gchar* pStr = gtk_buildable_get_name(GTK_BUILDABLE(pWidget));
+    OString aId(pStr, pStr ? strlen(pStr) : 0);
+    static_cast<MenuBar*>(pMenu)->HandleMenuButtonEvent(aId.toUInt32());
+}
 
-    GIcon* icon = g_themed_icon_new_with_default_fallbacks("window-close-symbolic");
-    GtkWidget* image = gtk_image_new_from_gicon(icon, GTK_ICON_SIZE_MENU);
-    gtk_widget_show(image);
-    g_object_unref(icon);
+bool GtkSalMenu::AddMenuBarButton(const SalMenuButtonItem& rNewItem)
+{
+    if (!mbMenuBar)
+        return false;
 
-    OUString sToolTip(VclResId(SV_HELPTEXT_CLOSEDOCUMENT));
-    gtk_widget_set_tooltip_text(mpCloseButton,
-        OUStringToOString(sToolTip, RTL_TEXTENCODING_UTF8).getStr());
+    if (!mpMenuBarContainerWidget)
+        return false;
 
-    gtk_widget_set_valign(mpCloseButton, GTK_ALIGN_CENTER);
+    GtkWidget* pImage = nullptr;
+    if (!!rNewItem.maImage)
+    {
+        SvMemoryStream* pMemStm = new SvMemoryStream;
+        vcl::PNGWriter aWriter(rNewItem.maImage.GetBitmapEx());
+        aWriter.Write(*pMemStm);
 
-    gtk_container_add(GTK_CONTAINER(mpCloseButton), image);
-    gtk_grid_attach(GTK_GRID(mpMenuBarContainerWidget), GTK_WIDGET(mpCloseButton), 1, 0, 1, 1);
-    gtk_widget_show_all(mpCloseButton);
+        GBytes *pBytes = g_bytes_new_with_free_func(pMemStm->GetData(),
+                                                    pMemStm->TellEnd(),
+                                                    DestroyMemoryStream,
+                                                    pMemStm);
+
+        GIcon *pIcon = g_bytes_icon_new(pBytes);
+        pImage = gtk_image_new_from_gicon(pIcon, GTK_ICON_SIZE_MENU);
+        g_object_unref(pIcon);
+    }
+
+    GtkWidget* pButton = AddButton(pImage);
+
+    maExtraButtons.emplace_back(rNewItem.mnId, pButton);
+
+    gtk_buildable_set_name(GTK_BUILDABLE(pButton), OString::number(rNewItem.mnId).getStr());
+
+    gtk_widget_set_tooltip_text(pButton, rNewItem.maToolTipText.toUtf8().getStr());
+
+    MenuBar *pVclMenuBar = static_cast<MenuBar*>(mpVCLMenu.get());
+    g_signal_connect(pButton, "clicked", G_CALLBACK(MenuButtonClicked), pVclMenuBar);
+
+    if (mpCloseButton)
+    {
+        gtk_grid_insert_next_to(GTK_GRID(mpMenuBarContainerWidget), mpCloseButton, GTK_POS_LEFT);
+        gtk_grid_attach_next_to(GTK_GRID(mpMenuBarContainerWidget), pButton, mpCloseButton,
+                                GTK_POS_LEFT, 1, 1);
+    }
+    else
+        gtk_grid_attach(GTK_GRID(mpMenuBarContainerWidget), pButton, 1, 0, 1, 1);
+
+    return true;
+}
+
+void GtkSalMenu::RemoveMenuBarButton( sal_uInt16 nId )
+{
+    const auto it = std::find_if(maExtraButtons.begin(), maExtraButtons.end(), [&nId](const auto &item) {
+        return item.first == nId; });
+    if (it != maExtraButtons.end())
+    {
+        gint nAttach(0);
+        gtk_container_child_get(GTK_CONTAINER(mpMenuBarContainerWidget), it->second, "left-attach", &nAttach, nullptr);
+        gtk_widget_destroy(it->second);
+        gtk_grid_remove_column(GTK_GRID(mpMenuBarContainerWidget), nAttach);
+        maExtraButtons.erase(it);
+    }
+}
+
+tools::Rectangle GtkSalMenu::GetMenuBarButtonRectPixel(sal_uInt16 nId, SalFrame* pReferenceFrame)
+{
+    if (!pReferenceFrame)
+        return tools::Rectangle();
+
+    const auto it = std::find_if(maExtraButtons.begin(), maExtraButtons.end(), [&nId](const auto &item) {
+        return item.first == nId; });
+    if (it == maExtraButtons.end())
+        return tools::Rectangle();
+
+    GtkWidget* pButton = it->second;
+
+    GtkSalFrame* pFrame = static_cast<GtkSalFrame*>(pReferenceFrame);
+
+    int x, y;
+    if (!gtk_widget_translate_coordinates(pButton, GTK_WIDGET(pFrame->getMouseEventWidget()), 0, 0, &x, &y))
+        return tools::Rectangle();
+
+    return tools::Rectangle(Point(x, y), Size(gtk_widget_get_allocated_width(pButton),
+                                              gtk_widget_get_allocated_height(pButton)));
 }
 
 //Typically when the menubar is deactivated we want the focus to return
@@ -725,7 +836,6 @@ gboolean GtkSalMenu::SignalKey(GdkEventKey const * pEvent)
 {
     if (pEvent->keyval == GDK_KEY_F6)
     {
-        fprintf(stderr, "GtkSalMenu::SignalKey\n");
         mbReturnFocusToDocument = false;
         gtk_menu_shell_cancel(GTK_MENU_SHELL(mpMenuBarWidget));
         //because we return false here, the keypress will continue
@@ -1020,15 +1130,6 @@ void GtkSalMenu::NativeSetItemText( unsigned nSection, unsigned nItemPos, const
         g_free( aLabel );
 }
 
-namespace
-{
-    void DestroyMemoryStream(gpointer data)
-    {
-        SvMemoryStream* pMemStm = static_cast<SvMemoryStream*>(data);
-        delete pMemStm;
-    }
-}
-
 void GtkSalMenu::NativeSetItemIcon( unsigned nSection, unsigned nItemPos, const Image& rImage )
 {
 #if GLIB_CHECK_VERSION(2,38,0)


More information about the Libreoffice-commits mailing list