Attached patch does what the subject says.
I'm not quite sure if I got everything right, especially
I can't make much sense of how the returned rectangles in
GetNativeControlRegion() are supposed to be done.
Regards,
--Mitch
From 9064d44f80da8511ee43687afebc999aeafa9985 Mon Sep 17 00:00:00 2001
From: Michael Natterer <mitch@gimp.org>
Date: Thu, 5 May 2011 09:13:37 +0200
Subject: [PATCH] Enable native sumbenu arrow drawing and implement it in GTK+
---
vcl/inc/vcl/menu.hxx | 4 +
vcl/inc/vcl/salnativewidgets.hxx | 1 +
vcl/source/window/menu.cxx | 93 +++++++++++++++++++++++++----
vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx | 64 ++++++++++++++++++++
4 files changed, 149 insertions(+), 13 deletions(-)
diff --git a/vcl/inc/vcl/menu.hxx b/vcl/inc/vcl/menu.hxx
index c052c14..6109491 100644
--- a/vcl/inc/vcl/menu.hxx
+++ b/vcl/inc/vcl/menu.hxx
@@ -199,6 +199,10 @@ protected:
// return value is Max( rCheckHeight, rRadioHeight )
SAL_DLLPRIVATE long ImplGetNativeCheckAndRadioSize( Window*, long& rCheckHeight,
long& rRadioHeight, long &rMaxWidth ) const;
+ // returns native submenu arrow size and spacing from right border
+ // return value is whether it's supported natively
+ SAL_DLLPRIVATE sal_Bool ImplGetNativeSubmenuArrowSize( Window* pWin, Size& rArrowSize,
long& rArrowSpacing ) const;
+
SAL_DLLPRIVATE void ImplAddDel( ImplMenuDelData &rDel );
SAL_DLLPRIVATE void ImplRemoveDel( ImplMenuDelData &rDel );
public:
diff --git a/vcl/inc/vcl/salnativewidgets.hxx b/vcl/inc/vcl/salnativewidgets.hxx
index 39e6c18..94fa162 100644
--- a/vcl/inc/vcl/salnativewidgets.hxx
+++ b/vcl/inc/vcl/salnativewidgets.hxx
@@ -178,6 +178,7 @@ typedef sal_uInt32 ControlPart;
#define PART_MENU_ITEM_CHECK_MARK 251
#define PART_MENU_ITEM_RADIO_MARK 252
#define PART_MENU_SEPARATOR 253
+#define PART_MENU_SUBMENU_ARROW 254
/* #i77549#
HACK: for scrollbars in case of thumb rect, page up and page down rect we
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
index 9984ee7..2afd2ea 100644
--- a/vcl/source/window/menu.cxx
+++ b/vcl/source/window/menu.cxx
@@ -2305,6 +2305,37 @@ long Menu::ImplGetNativeCheckAndRadioSize( Window* pWin, long& rCheckHeight,
lon
return (rCheckHeight > rRadioHeight) ? rCheckHeight : rRadioHeight;
}
+sal_Bool Menu::ImplGetNativeSubmenuArrowSize( Window* pWin, Size& rArrowSize, long& rArrowSpacing
) const
+{
+ ImplControlValue aVal;
+ Rectangle aNativeBounds;
+ Rectangle aNativeContent;
+ Point tmp( 0, 0 );
+ Rectangle aCtrlRegion( Rectangle( tmp, Size( 100, 15 ) ) );
+ if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP,
+ PART_MENU_SUBMENU_ARROW ) )
+ {
+ if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP),
+ ControlPart(PART_MENU_SUBMENU_ARROW),
+ aCtrlRegion,
+ ControlState(CTRL_STATE_ENABLED),
+ aVal,
+ OUString(),
+ aNativeBounds,
+ aNativeContent )
+ )
+ {
+ Size aSize( Size ( aNativeContent.GetWidth(),
+ aNativeContent.GetHeight() ) );
+ rArrowSize = aSize;
+ rArrowSpacing = aNativeBounds.GetWidth() - aNativeContent.GetWidth();
+
+ return sal_True;
+ }
+ }
+ return sal_False;
+}
+
// -----------------------------------------------------------------------
void Menu::ImplAddDel( ImplMenuDelData& rDel )
@@ -2853,21 +2884,57 @@ void Menu::ImplPaint( Window* pWin, sal_uInt16 nBorder, long nStartY,
MenuItemDa
// SubMenu?
if ( !bLayout && !bIsMenuBar && pData->pSubMenu )
{
- aTmpPos.X() = aOutSz.Width() - nFontHeight + nExtra - nOuterSpace;
- aTmpPos.Y() = aPos.Y();
- aTmpPos.Y() += nExtra/2;
- aTmpPos.Y() += ( pData->aSz.Height() / 2 ) - ( nFontHeight/4 );
- if ( pData->nBits & MIB_POPUPSELECT )
+ bool bNativeOk = false;
+ if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP,
+ PART_MENU_SUBMENU_ARROW ) )
{
- pWin->SetTextColor( rSettings.GetMenuTextColor() );
- Point aTmpPos2( aPos );
- aTmpPos2.X() = aOutSz.Width() - nFontHeight - nFontHeight/4;
- aDecoView.DrawFrame(
- Rectangle( aTmpPos2, Size( nFontHeight+nFontHeight/4,
pData->aSz.Height() ) ), FRAME_DRAW_GROUP );
+ ControlState nState = 0;
+ Size aTmpSz( 0, 0 );
+ long aSpacing = 0;
+
+ if( !ImplGetNativeSubmenuArrowSize( pWin,
+ aTmpSz, aSpacing ) )
+ {
+ aTmpSz = Size( nFontHeight, nFontHeight );
+ aSpacing = nOuterSpace;
+ }
+
+ if ( pData->bEnabled )
+ nState |= CTRL_STATE_ENABLED;
+ if ( bHighlighted )
+ nState |= CTRL_STATE_SELECTED;
+
+ aTmpPos.X() = aOutSz.Width() - aTmpSz.Width() - aSpacing - nOuterSpace;
+ aTmpPos.Y() = aPos.Y() + ( pData->aSz.Height() - aTmpSz.Height() ) / 2;
+ aTmpPos.Y() += nExtra/2;
+
+ Rectangle aItemRect( aTmpPos, aTmpSz );
+ MenupopupValue aVal( nTextPos-GUTTERBORDER, aItemRect );
+ bNativeOk = pWin->DrawNativeControl( CTRL_MENU_POPUP,
+ PART_MENU_SUBMENU_ARROW,
+ aItemRect,
+ nState,
+ aVal,
+ OUString() );
+ }
+ if( ! bNativeOk )
+ {
+ aTmpPos.X() = aOutSz.Width() - nFontHeight + nExtra - nOuterSpace;
+ aTmpPos.Y() = aPos.Y();
+ aTmpPos.Y() += nExtra/2;
+ aTmpPos.Y() += ( pData->aSz.Height() / 2 ) - ( nFontHeight/4 );
+ if ( pData->nBits & MIB_POPUPSELECT )
+ {
+ pWin->SetTextColor( rSettings.GetMenuTextColor() );
+ Point aTmpPos2( aPos );
+ aTmpPos2.X() = aOutSz.Width() - nFontHeight - nFontHeight/4;
+ aDecoView.DrawFrame(
+ Rectangle( aTmpPos2, Size( nFontHeight+nFontHeight/4,
pData->aSz.Height() ) ), FRAME_DRAW_GROUP );
+ }
+ aDecoView.DrawSymbol(
+ Rectangle( aTmpPos, Size( nFontHeight/2, nFontHeight/2 ) ),
+ SYMBOL_SPIN_RIGHT, pWin->GetTextColor(), nSymbolStyle );
}
- aDecoView.DrawSymbol(
- Rectangle( aTmpPos, Size( nFontHeight/2, nFontHeight/2 ) ),
- SYMBOL_SPIN_RIGHT, pWin->GetTextColor(), nSymbolStyle );
}
if ( pThisItemOnly && bHighlighted )
diff --git a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
index c37b366..8da8035 100644
--- a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
+++ b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
@@ -586,6 +586,7 @@ sal_Bool GtkSalGraphics::IsNativeControlSupported( ControlType nType, ControlPar
|| (nPart==PART_MENU_ITEM_CHECK_MARK)
|| (nPart==PART_MENU_ITEM_RADIO_MARK)
|| (nPart==PART_MENU_SEPARATOR)
+ || (nPart==PART_MENU_SUBMENU_ARROW)
)
) ||
((nType == CTRL_PROGRESS) &&
@@ -853,6 +854,7 @@ sal_Bool GtkSalGraphics::drawNativeControl( ControlType nType,
|| (nPart == PART_MENU_ITEM_CHECK_MARK)
|| (nPart == PART_MENU_ITEM_RADIO_MARK)
|| (nPart == PART_MENU_SEPARATOR)
+ || (nPart == PART_MENU_SUBMENU_ARROW)
)
)
{
@@ -1026,6 +1028,42 @@ sal_Bool GtkSalGraphics::getNativeControlRegion( ControlType nType,
rNativeContentRegion = aIndicatorRect;
returnVal = sal_True;
}
+ else if( nPart == PART_MENU_SUBMENU_ARROW )
+ {
+ GtkWidget* widget = gWidgetData[m_nScreen].gMenuItemMenuWidget;
+ GtkWidget* child;
+ PangoContext *context;
+ PangoFontMetrics *metrics;
+ gint arrow_size;
+ gint arrow_extent;
+ guint horizontal_padding;
+ gfloat arrow_scaling;
+
+ gtk_widget_style_get( widget,
+ "horizontal-padding", &horizontal_padding,
+ "arrow-scaling", &arrow_scaling,
+ NULL );
+
+ child = GTK_BIN( widget )->child;
+
+ context = gtk_widget_get_pango_context( child );
+ metrics = pango_context_get_metrics( context,
+ child->style->font_desc,
+ pango_context_get_language( context ) );
+
+ arrow_size = ( PANGO_PIXELS( pango_font_metrics_get_ascent( metrics ) +
+ pango_font_metrics_get_descent( metrics ) ));
+
+ pango_font_metrics_unref( metrics );
+
+ arrow_extent = arrow_size * arrow_scaling;
+
+ rNativeContentRegion = Rectangle( Point( 0, 0 ),
+ Size( arrow_extent, arrow_extent ));
+ rNativeBoundingRegion = Rectangle( Point( 0, 0 ),
+ Size( arrow_extent + horizontal_padding,
arrow_extent ));
+ returnVal = sal_True;
+ }
}
if( (nType == CTRL_RADIOBUTTON || nType == CTRL_CHECKBOX) )
{
@@ -2819,6 +2857,32 @@ sal_Bool GtkSalGraphics::NWPaintGTKPopupMenu(
"menuitem",
x, x + w, y + h / 2);
}
+ else if( nPart == PART_MENU_SUBMENU_ARROW )
+ {
+ GtkStateType nStateType = GTK_STATE_NORMAL;
+ GtkShadowType nShadowType;
+
+ if ( nState & CTRL_STATE_SELECTED )
+ nStateType = GTK_STATE_PRELIGHT;
+
+ NWSetWidgetState( gWidgetData[m_nScreen].gMenuItemMenuWidget,
+ nState, nStateType );
+
+ if ( nState & CTRL_STATE_PRESSED )
+ nShadowType = GTK_SHADOW_IN;
+ else
+ nShadowType = GTK_SHADOW_OUT;
+
+ gtk_paint_arrow( gWidgetData[m_nScreen].gMenuItemMenuWidget->style,
+ gdkDrawable,
+ nStateType,
+ nShadowType,
+ &clipRect,
+ gWidgetData[m_nScreen].gMenuItemMenuWidget,
+ "menuitem",
+ GTK_ARROW_RIGHT, TRUE,
+ x, y, w, h);
+ }
}
return( sal_True );
--
1.7.4.4
Context
- [Libreoffice] [PATCH] Enable native sumbenu arrow drawing and implement it in GTK+ · Michael Natterer
Privacy Policy |
Impressum (Legal Info) |
Copyright information: Unless otherwise specified, all text and images
on this website are licensed under the
Creative Commons Attribution-Share Alike 3.0 License.
This does not include the source code of LibreOffice, which is
licensed under the Mozilla Public License (
MPLv2).
"LibreOffice" and "The Document Foundation" are
registered trademarks of their corresponding registered owners or are
in actual use as trademarks in one or more countries. Their respective
logos and icons are also subject to international copyright laws. Use
thereof is explained in our
trademark policy.