Resolves: tdf#101699 get combobox junction right
gtk3-demo has examples of foreign drawing, follow
the patterns there to figure out what to do, add
stuff to gtk3-demo to demo what we need to do if
any particular case here is lacking
Change-Id: Ia1a22280161c97a3eab2d94fc4744fe971d31727
diff --git a/vcl/inc/unx/gtk/gtkgdi.hxx b/vcl/inc/unx/gtk/gtkgdi.hxx
index 802dd9a..b92ba5a 100644
--- a/vcl/inc/unx/gtk/gtkgdi.hxx
+++ b/vcl/inc/unx/gtk/gtkgdi.hxx
@@ -40,6 +40,15 @@ enum class GtkControlPart
RadioButton,
RadioButtonRadio,
Entry,
Combobox,
ComboboxBox,
ComboboxBoxEntry,
ComboboxBoxButton,
ComboboxBoxButtonBox,
Listbox,
ListboxBox,
ListboxBoxButton,
ListboxBoxButtonBox,
Arrow,
SpinButton,
SpinButtonUpButton,
@@ -131,10 +140,15 @@ private:
static GtkStyleContext *mpRadioMenuItemStyle;
static GtkStyleContext *mpSeparatorMenuItemStyle;
static GtkStyleContext *mpComboboxStyle;
static GtkStyleContext *mpComboboxBoxStyle;
static GtkStyleContext *mpComboboxEntryStyle;
static GtkStyleContext *mpComboboxButtonStyle;
static GtkStyleContext *mpComboboxButtonBoxStyle;
static GtkStyleContext *mpComboboxButtonArrowStyle;
static GtkStyleContext *mpListboxStyle;
static GtkStyleContext *mpListboxBoxStyle;
static GtkStyleContext *mpListboxButtonStyle;
static GtkStyleContext *mpListboxButtonBoxStyle;
static GtkStyleContext *mpListboxButtonArrowStyle;
static GtkStyleContext *mpFrameInStyle;
static GtkStyleContext *mpFrameOutStyle;
diff --git a/vcl/unx/gtk3/gtk3salnativewidgets-gtk.cxx b/vcl/unx/gtk3/gtk3salnativewidgets-gtk.cxx
index 0a3b2b6..829cf0d 100644
--- a/vcl/unx/gtk3/gtk3salnativewidgets-gtk.cxx
+++ b/vcl/unx/gtk3/gtk3salnativewidgets-gtk.cxx
@@ -52,10 +52,15 @@ GtkStyleContext* GtkSalGraphics::mpSpinStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpSpinUpStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpSpinDownStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpComboboxStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpComboboxBoxStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpComboboxEntryStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpComboboxButtonStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpComboboxButtonBoxStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpComboboxButtonArrowStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpListboxStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpListboxBoxStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpListboxButtonStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpListboxButtonBoxStyle= nullptr;
GtkStyleContext* GtkSalGraphics::mpListboxButtonArrowStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpFrameInStyle = nullptr;
GtkStyleContext* GtkSalGraphics::mpFrameOutStyle = nullptr;
@@ -294,8 +299,10 @@ static GtkWidget* gTreeViewWidget;
namespace
{
void render_common(GtkStyleContext *pContext, cairo_t *cr, const Rectangle &rIn)
Rectangle render_common(GtkStyleContext *pContext, cairo_t *cr, const Rectangle &rIn, GtkStateFlags flags)
{
gtk_style_context_set_state(pContext, flags);
Rectangle aRect(rIn);
GtkBorder margin;
gtk_style_context_get_margin(pContext, gtk_style_context_get_state(pContext), &margin);
@@ -309,6 +316,17 @@ namespace
aRect.GetWidth(), aRect.GetHeight());
gtk_render_frame(pContext, cr, aRect.Left(), aRect.Top(),
aRect.GetWidth(), aRect.GetHeight());
GtkBorder border, padding;
gtk_style_context_get_border(pContext, gtk_style_context_get_state(pContext), &border);
gtk_style_context_get_padding(pContext, gtk_style_context_get_state(pContext), &padding);
aRect.Left() += border.left + padding.left;
aRect.Top() += border.top + padding.top;
aRect.Right() -= border.right + padding.right;
aRect.Bottom() -= border.bottom + padding.bottom;
return aRect;
}
}
@@ -766,8 +784,6 @@ void GtkSalGraphics::PaintCombobox( GtkStateFlags flags, cairo_t *cr,
areaRect = rControlRectangle;
buttonRect = NWGetComboBoxButtonRect( nType, ControlPart::ButtonDown, areaRect );
if( nPart == ControlPart::ButtonDown )
buttonRect.Left() += 1;
Rectangle aEditBoxRect( areaRect );
aEditBoxRect.SetSize( Size( areaRect.GetWidth() - buttonRect.GetWidth(), aEditBoxRect.GetHeight() ) );
@@ -800,36 +816,39 @@ void GtkSalGraphics::PaintCombobox( GtkStateFlags flags, cairo_t *cr,
if (nType == ControlType::Combobox)
{
gtk_style_context_save(mpComboboxButtonStyle);
gtk_style_context_set_state(mpComboboxButtonStyle, flags);
if( nPart == ControlPart::Entire )
{
GtkJunctionSides eJuncSides = gtk_style_context_get_junction_sides(mpEntryStyle);
gtk_style_context_set_state(mpEntryStyle, flags);
if (AllSettings::GetLayoutRTL())
gtk_style_context_set_junction_sides(mpEntryStyle, GTK_JUNCTION_LEFT);
else
gtk_style_context_set_junction_sides(mpEntryStyle, GTK_JUNCTION_RIGHT);
render_common(mpComboboxStyle, cr, aRect);
render_common(mpComboboxStyle, cr, aRect, flags);
render_common(mpComboboxBoxStyle, cr, aRect, flags);
Rectangle aEntryRect(Point(aEditBoxRect.Left() - areaRect.Left(),
aEditBoxRect.Top() - areaRect.Top()),
Size(aEditBoxRect.GetWidth(), aEditBoxRect.GetHeight()));
render_common(mpEntryStyle, cr, aEntryRect);
gtk_style_context_set_junction_sides(mpEntryStyle, eJuncSides);
GtkJunctionSides eJuncSides = gtk_style_context_get_junction_sides(mpComboboxEntryStyle);
if (AllSettings::GetLayoutRTL())
gtk_style_context_set_junction_sides(mpComboboxEntryStyle, GTK_JUNCTION_LEFT);
else
gtk_style_context_set_junction_sides(mpComboboxEntryStyle, GTK_JUNCTION_RIGHT);
render_common(mpComboboxEntryStyle, cr, aEntryRect, flags);
gtk_style_context_set_junction_sides(mpComboboxEntryStyle, eJuncSides);
}
Rectangle aButtonRect(Point(buttonRect.Left() - areaRect.Left(), buttonRect.Top() - areaRect.Top()),
Size(buttonRect.GetWidth(), buttonRect.GetHeight()));
render_common(mpComboboxButtonStyle, cr, aButtonRect);
GtkJunctionSides eJuncSides = gtk_style_context_get_junction_sides(mpComboboxButtonStyle);
if (AllSettings::GetLayoutRTL())
gtk_style_context_set_junction_sides(mpComboboxButtonStyle, GTK_JUNCTION_RIGHT);
else
gtk_style_context_set_junction_sides(mpComboboxButtonStyle, GTK_JUNCTION_LEFT);
Rectangle aContentsRect = render_common(mpComboboxButtonStyle, cr, aButtonRect, flags);
gtk_style_context_set_junction_sides(mpComboboxButtonStyle, eJuncSides);
render_common(mpComboboxButtonBoxStyle, cr, aContentsRect, flags);
render_common(mpComboboxButtonArrowStyle, cr, aContentsRect, flags);
gtk_render_arrow(mpComboboxButtonArrowStyle, cr,
G_PI,
(arrowRect.Left() - areaRect.Left()), (arrowRect.Top() - areaRect.Top()),
arrowRect.GetWidth() );
gtk_style_context_restore(mpComboboxButtonStyle);
}
else if (nType == ControlType::Listbox)
{
@@ -842,28 +861,59 @@ void GtkSalGraphics::PaintCombobox( GtkStateFlags flags, cairo_t *cr,
}
else
{
gtk_style_context_save(mpListboxButtonStyle);
gtk_style_context_set_state(mpListboxButtonStyle, flags);
render_common(mpListboxStyle, cr, aRect, flags);
render_common(mpListboxBoxStyle, cr, aRect, flags);
render_common(mpListboxStyle, cr, aRect);
render_common(mpListboxButtonStyle, cr, aRect);
Rectangle aContentsRect = render_common(mpListboxButtonStyle, cr, aRect, flags);
render_common(mpListboxButtonBoxStyle, cr, aContentsRect, flags);
render_common(mpListboxButtonArrowStyle, cr, aContentsRect, flags);
gtk_render_arrow(mpListboxButtonArrowStyle, cr,
G_PI,
(arrowRect.Left() - areaRect.Left()), (arrowRect.Top() - areaRect.Top()),
arrowRect.GetWidth() );
gtk_style_context_restore(mpListboxButtonStyle);
}
}
}
typedef void (*gtk_widget_path_iter_set_object_nameFunc)(GtkWidgetPath *, guint, const char*);
static GtkStyleContext* createNewStyleContext(gtk_widget_path_iter_set_object_nameFunc set_object_name,
GtkControlPart ePart, GtkStyleContext* parent)
static void appendComboEntry(GtkWidgetPath* pSiblingsPath, gtk_widget_path_iter_set_object_nameFunc set_object_name)
{
GtkWidgetPath *path = parent ? gtk_widget_path_copy(gtk_style_context_get_path(parent)) : gtk_widget_path_new();
gtk_widget_path_append_type(pSiblingsPath, GTK_TYPE_ENTRY);
set_object_name(pSiblingsPath, -1, "entry");
gtk_widget_path_iter_add_class(pSiblingsPath, -1, "combo");
}
static void appendComboButton(GtkWidgetPath* pSiblingsPath, gtk_widget_path_iter_set_object_nameFunc set_object_name)
{
gtk_widget_path_append_type(pSiblingsPath, GTK_TYPE_BUTTON);
set_object_name(pSiblingsPath, -1, "button");
gtk_widget_path_iter_add_class(pSiblingsPath, -1, "combo");
}
static GtkWidgetPath* buildLTRComboSiblingsPath(gtk_widget_path_iter_set_object_nameFunc set_object_name)
{
GtkWidgetPath* pSiblingsPath = gtk_widget_path_new();
appendComboEntry(pSiblingsPath, set_object_name);
appendComboButton(pSiblingsPath, set_object_name);
return pSiblingsPath;
}
static GtkWidgetPath* buildRTLComboSiblingsPath(gtk_widget_path_iter_set_object_nameFunc set_object_name)
{
GtkWidgetPath* pSiblingsPath = gtk_widget_path_new();
appendComboButton(pSiblingsPath, set_object_name);
appendComboEntry(pSiblingsPath, set_object_name);
return pSiblingsPath;
}
static void appendPathElement(GtkWidgetPath* path, GtkControlPart ePart, gtk_widget_path_iter_set_object_nameFunc set_object_name)
{
switch (ePart)
{
case GtkControlPart::Button:
@@ -899,6 +949,68 @@ static GtkStyleContext* createNewStyleContext(gtk_widget_path_iter_set_object_na
gtk_widget_path_append_type(path, GTK_TYPE_ENTRY);
set_object_name(path, -1, "entry");
break;
case GtkControlPart::Combobox:
case GtkControlPart::Listbox:
gtk_widget_path_append_type(path, G_TYPE_NONE);
set_object_name(path, -1, "combobox");
break;
case GtkControlPart::ComboboxBox:
case GtkControlPart::ListboxBox:
gtk_widget_path_append_type(path, G_TYPE_NONE);
set_object_name(path, -1, "box");
gtk_widget_path_iter_add_class(path, -1, "horizontal");
gtk_widget_path_iter_add_class(path, -1, "linked");
break;
case GtkControlPart::ComboboxBoxEntry:
{
GtkWidgetPath* pSiblingsPath;
if (AllSettings::GetLayoutRTL())
{
pSiblingsPath = buildRTLComboSiblingsPath(set_object_name);
gtk_widget_path_append_with_siblings(path, pSiblingsPath, 1);
}
else
{
pSiblingsPath = buildLTRComboSiblingsPath(set_object_name);
gtk_widget_path_append_with_siblings(path, pSiblingsPath, 0);
}
gtk_widget_path_unref(pSiblingsPath);
break;
}
case GtkControlPart::ComboboxBoxButton:
{
GtkWidgetPath* pSiblingsPath;
if (AllSettings::GetLayoutRTL())
{
pSiblingsPath = buildRTLComboSiblingsPath(set_object_name);
gtk_widget_path_append_with_siblings(path, pSiblingsPath, 0);
}
else
{
pSiblingsPath = buildLTRComboSiblingsPath(set_object_name);
gtk_widget_path_append_with_siblings(path, pSiblingsPath, 1);
}
gtk_widget_path_unref(pSiblingsPath);
break;
}
case GtkControlPart::ListboxBoxButton:
{
GtkWidgetPath* pSiblingsPath = gtk_widget_path_new();
gtk_widget_path_append_type(pSiblingsPath, GTK_TYPE_BUTTON);
set_object_name(pSiblingsPath, -1, "button");
gtk_widget_path_iter_add_class(pSiblingsPath, -1, "combo");
gtk_widget_path_append_with_siblings(path, pSiblingsPath, 0);
gtk_widget_path_unref(pSiblingsPath);
break;
}
case GtkControlPart::ComboboxBoxButtonBox:
case GtkControlPart::ListboxBoxButtonBox:
gtk_widget_path_append_type(path, G_TYPE_NONE);
set_object_name(path, -1, "box");
gtk_widget_path_iter_add_class(path, -1, "horizontal");
break;
case GtkControlPart::SpinButton:
gtk_widget_path_append_type(path, GTK_TYPE_SPIN_BUTTON);
set_object_name(path, -1, "spinbutton");
@@ -1015,6 +1127,14 @@ static GtkStyleContext* createNewStyleContext(gtk_widget_path_iter_set_object_na
gtk_widget_path_iter_add_class(path, -1, "frame");
break;
}
}
static GtkStyleContext* createNewStyleContext(gtk_widget_path_iter_set_object_nameFunc set_object_name,
GtkControlPart ePart, GtkStyleContext* parent)
{
GtkWidgetPath *path = parent ? gtk_widget_path_copy(gtk_style_context_get_path(parent)) : gtk_widget_path_new();
appendPathElement(path, ePart, set_object_name);
GtkStyleContext* context = gtk_style_context_new();
gtk_style_context_set_path(context, path);
@@ -1059,9 +1179,28 @@ static GtkStyleContext* createOldStyleContext(GtkControlPart ePart, GtkStyleCont
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_BUTTON);
break;
case GtkControlPart::Entry:
case GtkControlPart::ComboboxBoxEntry:
gtk_widget_path_append_type(path, GTK_TYPE_ENTRY);
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_ENTRY);
break;
case GtkControlPart::Combobox:
gtk_widget_path_append_type(path, GTK_TYPE_COMBO_BOX_TEXT);
break;
case GtkControlPart::Listbox:
gtk_widget_path_append_type(path, GTK_TYPE_COMBO_BOX);
break;
break;
case GtkControlPart::ComboboxBoxButton:
case GtkControlPart::ListboxBoxButton:
gtk_widget_path_append_type(path, GTK_TYPE_TOGGLE_BUTTON);
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_BUTTON);
gtk_widget_path_iter_add_class(path, -1, "the-button-in-the-combobox");
break;
case GtkControlPart::ComboboxBox:
case GtkControlPart::ListboxBox:
case GtkControlPart::ComboboxBoxButtonBox:
case GtkControlPart::ListboxBoxButtonBox:
break;
case GtkControlPart::SpinButton:
gtk_widget_path_append_type(path, GTK_TYPE_SPIN_BUTTON);
gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_SPINBUTTON);
@@ -2415,8 +2554,6 @@ GtkSalGraphics::GtkSalGraphics( GtkSalFrame *pFrame, GtkWidget *pWindow )
reinterpret_cast<gtk_widget_path_iter_set_object_nameFunc>(osl_getAsciiFunctionSymbol(nullptr,
"gtk_widget_path_iter_set_object_name"));
fprintf(stderr, "set_object_name is %p\n", set_object_name);
gCacheWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gDumbContainer = gtk_fixed_new();
gtk_container_add(GTK_CONTAINER(gCacheWindow), gDumbContainer);
@@ -2509,16 +2646,23 @@ GtkSalGraphics::GtkSalGraphics( GtkSalFrame *pFrame, GtkWidget *pWindow )
/* Combobox */
gComboBox = gtk_combo_box_text_new_with_entry();
getStyleContext(&mpComboboxStyle, gComboBox);
mpComboboxButtonStyle = createStyleContext(set_object_name, GtkControlPart::Button, mpComboboxStyle);
mpComboboxButtonArrowStyle = createStyleContext(set_object_name, GtkControlPart::Arrow, mpComboboxButtonStyle);
gtk_container_add(GTK_CONTAINER(gDumbContainer), gComboBox);
mpComboboxStyle = createStyleContext(set_object_name, GtkControlPart::Combobox);
mpComboboxBoxStyle = createStyleContext(set_object_name, GtkControlPart::ComboboxBox, mpComboboxStyle);
mpComboboxEntryStyle = createStyleContext(set_object_name, GtkControlPart::ComboboxBoxEntry, mpComboboxBoxStyle);
mpComboboxButtonStyle = createStyleContext(set_object_name, GtkControlPart::ComboboxBoxButton, mpComboboxBoxStyle);
mpComboboxButtonBoxStyle = createStyleContext(set_object_name, GtkControlPart::ComboboxBoxButtonBox, mpComboboxButtonStyle);
mpComboboxButtonArrowStyle = createStyleContext(set_object_name, GtkControlPart::Arrow, mpComboboxButtonBoxStyle);
/* Listbox */
gListBox = gtk_combo_box_text_new();
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(gListBox), "sample");
getStyleContext(&mpListboxStyle, gListBox);
mpListboxButtonStyle = createStyleContext(set_object_name, GtkControlPart::Button, mpListboxStyle);
mpListboxButtonArrowStyle = createStyleContext(set_object_name, GtkControlPart::Arrow, mpListboxButtonStyle);
gtk_container_add(GTK_CONTAINER(gDumbContainer), gListBox);
mpListboxStyle = createStyleContext(set_object_name, GtkControlPart::Listbox);
mpListboxBoxStyle = createStyleContext(set_object_name, GtkControlPart::ListboxBox, mpListboxStyle);
mpListboxButtonStyle = createStyleContext(set_object_name, GtkControlPart::ListboxBoxButton, mpListboxBoxStyle);
mpListboxButtonBoxStyle = createStyleContext(set_object_name, GtkControlPart::ListboxBoxButtonBox, mpListboxButtonStyle);
mpListboxButtonArrowStyle = createStyleContext(set_object_name, GtkControlPart::Arrow, mpListboxButtonBoxStyle);
/* Frames */
mpFrameOutStyle = mpFrameInStyle = createStyleContext(set_object_name, GtkControlPart::FrameBorder);