include/vcl/menu.hxx | 3 + vcl/inc/salmenu.hxx | 4 + vcl/inc/unx/gtk/gtksalmenu.hxx | 11 +++++ vcl/source/app/salvtables.cxx | 9 ++++ vcl/source/window/dockingarea.cxx | 9 ---- vcl/source/window/menu.cxx | 15 +++++++ vcl/source/window/menubarwindow.cxx | 3 + vcl/unx/gtk/gtksalmenu.cxx | 75 ++++++++++++++++++++++++++++++++++++ 8 files changed, 122 insertions(+), 7 deletions(-)
New commits: commit e586d6eca6686ab987195913dad27d89e65d3d5b Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Tue Jan 22 11:21:27 2019 +0000 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Fri Jan 25 09:27:47 2019 +0100 Resolves: tdf#122241 support persona header in native gtk3 menubar Change-Id: Ia4485ec4c342c86f40e8e0bb7e5e1af1a47bb9b9 Reviewed-on: https://gerrit.libreoffice.org/66735 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/include/vcl/menu.hxx b/include/vcl/menu.hxx index 0141582f1af1..75a178419a66 100644 --- a/include/vcl/menu.hxx +++ b/include/vcl/menu.hxx @@ -470,6 +470,9 @@ public: tools::Rectangle GetMenuBarButtonRectPixel( sal_uInt16 nId ); void RemoveMenuBarButton( sal_uInt16 nId ); void LayoutChanged(); + // get the height of the menubar, return the native menubar height if that is active or the vcl + // one if not + int GetMenuBarHeight() const; }; inline MenuBar& MenuBar::operator=( const MenuBar& rMenu ) diff --git a/vcl/inc/salmenu.hxx b/vcl/inc/salmenu.hxx index 169d887068da..0b6cd9e22481 100644 --- a/vcl/inc/salmenu.hxx +++ b/vcl/inc/salmenu.hxx @@ -90,6 +90,10 @@ public: // return Rectangle( Point( -1, -1 ), Size( 1, 1 ) ) if menu bar buttons implemented // but rectangle cannot be determined virtual tools::Rectangle GetMenuBarButtonRectPixel( sal_uInt16 i_nItemId, SalFrame* i_pReferenceFrame ); + + virtual int GetMenuBarHeight() const; + + virtual void ApplyPersona(); }; #endif // INCLUDED_VCL_INC_SALMENU_HXX diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx index 9ab448857085..bdacee7ca178 100644 --- a/vcl/inc/unx/gtk/gtksalmenu.hxx +++ b/vcl/inc/unx/gtk/gtksalmenu.hxx @@ -20,6 +20,7 @@ #include <salmenu.hxx> #include <unx/gtk/gtkframe.hxx> +#include <unotools/tempfile.hxx> #include <vcl/idle.hxx> #if GTK_CHECK_VERSION(3,0,0) @@ -40,6 +41,10 @@ # endif #endif +#if !GTK_CHECK_VERSION(3,0,0) +typedef void GtkCssProvider; +#endif + class MenuItemList; class GtkSalMenuItem; @@ -55,8 +60,12 @@ private: bool mbReturnFocusToDocument; bool mbAddedGrab; GtkWidget* mpMenuBarContainerWidget; + std::unique_ptr<utl::TempFile> mxPersonaImage; + BitmapEx maPersonaBitmap; GtkWidget* mpMenuAllowShrinkWidget; GtkWidget* mpMenuBarWidget; + GtkCssProvider* mpMenuBarContainerProvider; + GtkCssProvider* mpMenuBarProvider; GtkWidget* mpCloseButton; VclPtr<Menu> mpVCLMenu; GtkSalMenu* mpParentSalMenu; @@ -137,6 +146,8 @@ public: virtual void ShowCloseButton(bool bShow) override; virtual bool CanGetFocus() const override; virtual bool TakeFocus() override; + virtual int GetMenuBarHeight() const override; + virtual void ApplyPersona() override; }; class GtkSalMenuItem : public SalMenuItem diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index 83e12c3eb41c..6be5e24f7bd4 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -200,6 +200,15 @@ tools::Rectangle SalMenu::GetMenuBarButtonRectPixel( sal_uInt16, SalFrame* ) return tools::Rectangle(); } +int SalMenu::GetMenuBarHeight() const +{ + return 0; +} + +void SalMenu::ApplyPersona() +{ +} + SalMenuItem::~SalMenuItem() { } diff --git a/vcl/source/window/dockingarea.cxx b/vcl/source/window/dockingarea.cxx index 647f87bf3d36..f9fb0234f002 100644 --- a/vcl/source/window/dockingarea.cxx +++ b/vcl/source/window/dockingarea.cxx @@ -130,14 +130,9 @@ void DockingAreaWindow::ApplySettings(vcl::RenderContext& rRenderContext) // we need to shift the bitmap vertically so that it spans over the // menubar conveniently - long nMenubarHeight = 0; SystemWindow* pSysWin = GetSystemWindow(); - if (pSysWin && pSysWin->GetMenuBar()) - { - vcl::Window* pMenubarWin = pSysWin->GetMenuBar()->GetWindow(); - if (pMenubarWin) - nMenubarHeight = pMenubarWin->GetOutputHeightPixel(); - } + MenuBar* pMenuBar = pSysWin ? pSysWin->GetMenuBar() : nullptr; + int nMenubarHeight = pMenuBar ? pMenuBar->GetMenuBarHeight() : 0; aWallpaper.SetRect(tools::Rectangle(Point(0, -nMenubarHeight), Size(rRenderContext.GetOutputWidthPixel(), rRenderContext.GetOutputHeightPixel() + nMenubarHeight))); diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx index b9833ae4a503..65abfd7ec85e 100644 --- a/vcl/source/window/menu.cxx +++ b/vcl/source/window/menu.cxx @@ -2672,6 +2672,21 @@ bool MenuBar::HandleMenuButtonEvent( sal_uInt16 i_nButtonId ) return pMenuWin && pMenuWin->HandleMenuButtonEvent(i_nButtonId); } +int MenuBar::GetMenuBarHeight() const +{ + MenuBar* pMenuBar = const_cast<MenuBar*>(this); + const SalMenu *pNativeMenu = pMenuBar->ImplGetSalMenu(); + int nMenubarHeight; + if (pNativeMenu) + nMenubarHeight = pNativeMenu->GetMenuBarHeight(); + else + { + vcl::Window* pMenubarWin = GetWindow(); + nMenubarHeight = pMenubarWin ? pMenubarWin->GetOutputHeightPixel() : 0; + } + return nMenubarHeight; +} + // bool PopupMenu::bAnyPopupInExecute = false; MenuFloatingWindow * PopupMenu::ImplGetFloatingWindow() const { diff --git a/vcl/source/window/menubarwindow.cxx b/vcl/source/window/menubarwindow.cxx index a4c33051046b..25ab264bc9d9 100644 --- a/vcl/source/window/menubarwindow.cxx +++ b/vcl/source/window/menubarwindow.cxx @@ -1078,6 +1078,9 @@ void MenuBarWindow::ApplySettings(vcl::RenderContext& rRenderContext) SetPointFont(rRenderContext, rStyleSettings.GetMenuFont()); const BitmapEx& rPersonaBitmap = Application::GetSettings().GetStyleSettings().GetPersonaHeader(); + SalMenu *pNativeMenu = pMenu ? pMenu->ImplGetSalMenu() : nullptr; + if (pNativeMenu) + pNativeMenu->ApplyPersona(); if (!rPersonaBitmap.IsEmpty()) { Wallpaper aWallpaper(rPersonaBitmap); diff --git a/vcl/unx/gtk/gtksalmenu.cxx b/vcl/unx/gtk/gtksalmenu.cxx index 8329c376eda7..538cb0aa680d 100644 --- a/vcl/unx/gtk/gtksalmenu.cxx +++ b/vcl/unx/gtk/gtksalmenu.cxx @@ -534,6 +534,8 @@ GtkSalMenu::GtkSalMenu( bool bMenuBar ) : mpMenuBarContainerWidget( nullptr ), mpMenuAllowShrinkWidget( nullptr ), mpMenuBarWidget( nullptr ), + mpMenuBarContainerProvider( nullptr ), + mpMenuBarProvider( nullptr ), mpCloseButton( nullptr ), mpVCLMenu( nullptr ), mpParentSalMenu( nullptr ), @@ -834,6 +836,7 @@ void GtkSalMenu::CreateMenuBarWidget() gtk_grid_attach(GTK_GRID(mpMenuBarContainerWidget), mpMenuAllowShrinkWidget, 0, 0, 1, 1); mpMenuBarWidget = gtk_menu_bar_new_from_model(mpMenuModel); + gtk_widget_insert_action_group(mpMenuBarWidget, "win", mpActionGroup); gtk_widget_set_hexpand(GTK_WIDGET(mpMenuBarWidget), true); gtk_widget_set_hexpand(mpMenuAllowShrinkWidget, true); @@ -845,12 +848,75 @@ void GtkSalMenu::CreateMenuBarWidget() gtk_widget_show_all(mpMenuBarContainerWidget); ShowCloseButton( static_cast<MenuBar*>(mpVCLMenu.get())->HasCloseButton() ); + + ApplyPersona(); #else (void)mpMenuAllowShrinkWidget; (void)mpMenuBarContainerWidget; #endif } +void GtkSalMenu::ApplyPersona() +{ +#if GTK_CHECK_VERSION(3,0,0) + assert(mbMenuBar); + // I'm dubious about the persona theming feature, but as it exists, lets try and support + // it, apply the image to the mpMenuBarContainerWidget + const BitmapEx& rPersonaBitmap = Application::GetSettings().GetStyleSettings().GetPersonaHeader(); + + GtkStyleContext *pMenuBarContainerContext = gtk_widget_get_style_context(GTK_WIDGET(mpMenuBarContainerWidget)); + if (mpMenuBarContainerProvider) + { + gtk_style_context_remove_provider(pMenuBarContainerContext, GTK_STYLE_PROVIDER(mpMenuBarContainerProvider)); + mpMenuBarContainerProvider = nullptr; + } + GtkStyleContext *pMenuBarContext = gtk_widget_get_style_context(GTK_WIDGET(mpMenuBarWidget)); + if (mpMenuBarProvider) + { + gtk_style_context_remove_provider(pMenuBarContext, GTK_STYLE_PROVIDER(mpMenuBarProvider)); + mpMenuBarProvider = nullptr; + } + + if (!rPersonaBitmap.IsEmpty()) + { + if (maPersonaBitmap != rPersonaBitmap) + { + vcl::PNGWriter aPNGWriter(rPersonaBitmap); + mxPersonaImage.reset(new utl::TempFile); + mxPersonaImage->EnableKillingFile(true); + SvStream* pStream = mxPersonaImage->GetStream(StreamMode::WRITE); + aPNGWriter.Write(*pStream); + mxPersonaImage->CloseStream(); + } + + mpMenuBarContainerProvider = gtk_css_provider_new(); + OUString aBuffer = "* { background-image: url(\"" + mxPersonaImage->GetURL() + "\"); background-position: top right; }"; + OString aResult = OUStringToOString(aBuffer, RTL_TEXTENCODING_UTF8); + gtk_css_provider_load_from_data(mpMenuBarContainerProvider, aResult.getStr(), aResult.getLength(), nullptr); + gtk_style_context_add_provider(pMenuBarContainerContext, GTK_STYLE_PROVIDER(mpMenuBarContainerProvider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + + + // force the menubar to be transparent when persona is active otherwise for + // me the menubar becomes gray when its in the backdrop + mpMenuBarProvider = gtk_css_provider_new(); + static const gchar data[] = "* { " + "background-image: none;" + "background-color: transparent;" + "}"; + gtk_css_provider_load_from_data(mpMenuBarProvider, data, -1, nullptr); + gtk_style_context_add_provider(pMenuBarContext, + GTK_STYLE_PROVIDER(mpMenuBarProvider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + } + maPersonaBitmap = rPersonaBitmap; +#else + (void)maPersonaBitmap; + (void)mpMenuBarContainerProvider; + (void)mpMenuBarProvider; +#endif +} + void GtkSalMenu::DestroyMenuBarWidget() { #if GTK_CHECK_VERSION(3,0,0) @@ -1331,6 +1397,15 @@ void GtkSalMenu::GetSystemMenuData( SystemMenuData* ) { } +int GtkSalMenu::GetMenuBarHeight() const +{ +#if GTK_CHECK_VERSION(3,0,0) + return mpMenuBarWidget ? gtk_widget_get_allocated_height(mpMenuBarWidget) : 0; +#else + return 0; +#endif +} + /* * GtkSalMenuItem */ _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits