зеркало из https://github.com/mozilla/pjs.git
Bug 415163 - "GTK location bar drop-down button arrow is misaligned" [p=frnchfrgg-mozbugs@altern.org (RIVAUD Julien [_FrnchFrgg_]) r=Ryan r=twanno r=Ventron sr=roc a1.9=beltzner]
This commit is contained in:
Родитель
ac87922be6
Коммит
a817f1c177
|
@ -950,7 +950,7 @@ toolbar[iconsize="small"] #paste-button[disabled="true"] {
|
|||
#autocomplete-security-wrapper {
|
||||
/* keep the URL bar content LTR */
|
||||
direction: ltr;
|
||||
-moz-box-align: center;
|
||||
-moz-box-align: stretch;
|
||||
/* cover the white gap between the text field and the drop down button */
|
||||
margin-right: -3px;
|
||||
}
|
||||
|
|
|
@ -99,6 +99,7 @@ static GtkShadowType gToolbarShadowType;
|
|||
|
||||
static style_prop_t style_prop_func;
|
||||
static gboolean have_menu_shadow_type;
|
||||
static gboolean have_arrow_scaling;
|
||||
static gboolean is_initialized;
|
||||
|
||||
gint
|
||||
|
@ -253,54 +254,120 @@ ensure_option_menu_widget()
|
|||
return MOZ_GTK_SUCCESS;
|
||||
}
|
||||
|
||||
static gint
|
||||
ensure_combo_box_entry_widget()
|
||||
{
|
||||
if (!gComboBoxEntryWidget) {
|
||||
gComboBoxEntryWidget = gtk_combo_box_entry_new();
|
||||
setup_widget_prototype(gComboBoxEntryWidget);
|
||||
}
|
||||
return MOZ_GTK_SUCCESS;
|
||||
}
|
||||
/* We need to have pointers to the inner widgets (entry, button, arrow) of
|
||||
* the ComboBoxEntry to get the correct rendering from theme engines which
|
||||
* special cases their look. Since the inner layout can change, we ask GTK
|
||||
* to NULL our pointers when they are about to become invalid because the
|
||||
* corresponding widgets don't exist anymore. It's the role of
|
||||
* g_object_add_weak_pointer().
|
||||
* Note that if we don't find the inner widgets (which shouldn't happen), we
|
||||
* fallback to use generic "non-inner" widgets, and they don't need that kind
|
||||
* of weak pointer since they are explicit children of gProtoWindow and as
|
||||
* such GTK holds a strong reference to them. */
|
||||
|
||||
static gint
|
||||
ensure_dropdown_entry_widget()
|
||||
static void
|
||||
moz_gtk_get_combo_box_entry_inner_widgets(GtkWidget *widget,
|
||||
gpointer client_data)
|
||||
{
|
||||
if (!gDropdownEntryWidget) {
|
||||
ensure_combo_box_entry_widget();
|
||||
|
||||
gDropdownEntryWidget = GTK_BIN(gComboBoxEntryWidget)->child;
|
||||
gtk_widget_realize(gDropdownEntryWidget);
|
||||
}
|
||||
return MOZ_GTK_SUCCESS;
|
||||
if (GTK_IS_TOGGLE_BUTTON(widget)) {
|
||||
gDropdownButtonWidget = widget;
|
||||
g_object_add_weak_pointer(G_OBJECT(widget),
|
||||
(gpointer) &gDropdownButtonWidget);
|
||||
} else if (GTK_IS_ENTRY(widget)) {
|
||||
gDropdownEntryWidget = widget;
|
||||
g_object_add_weak_pointer(G_OBJECT(widget),
|
||||
(gpointer) &gDropdownEntryWidget);
|
||||
} else
|
||||
return;
|
||||
gtk_widget_realize(widget);
|
||||
}
|
||||
|
||||
static void
|
||||
moz_gtk_get_dropdown_button(GtkWidget *widget,
|
||||
gpointer client_data)
|
||||
moz_gtk_get_combo_box_entry_arrow(GtkWidget *widget, gpointer client_data)
|
||||
{
|
||||
if (GTK_IS_TOGGLE_BUTTON(widget))
|
||||
gDropdownButtonWidget = widget;
|
||||
if (GTK_IS_ARROW(widget)) {
|
||||
gArrowWidget = widget;
|
||||
g_object_add_weak_pointer(G_OBJECT(widget),
|
||||
(gpointer) &gArrowWidget);
|
||||
gtk_widget_realize(widget);
|
||||
}
|
||||
}
|
||||
|
||||
static gint
|
||||
ensure_arrow_widget()
|
||||
ensure_combo_box_entry_widgets()
|
||||
{
|
||||
if (!gArrowWidget) {
|
||||
ensure_combo_box_entry_widget();
|
||||
if (!gDropdownEntryWidget ||
|
||||
!gDropdownButtonWidget ||
|
||||
!gArrowWidget) {
|
||||
GtkWidget* buttonChild;
|
||||
|
||||
/* Create a ComboBoxEntry if needed */
|
||||
if (!gComboBoxEntryWidget) {
|
||||
gComboBoxEntryWidget = gtk_combo_box_entry_new();
|
||||
setup_widget_prototype(gComboBoxEntryWidget);
|
||||
}
|
||||
|
||||
/* Get its inner Entry and Button */
|
||||
gtk_container_forall(GTK_CONTAINER(gComboBoxEntryWidget),
|
||||
moz_gtk_get_dropdown_button,
|
||||
moz_gtk_get_combo_box_entry_inner_widgets,
|
||||
NULL);
|
||||
|
||||
gArrowWidget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
|
||||
gtk_container_add(GTK_CONTAINER(GTK_BIN(gDropdownButtonWidget)->child),
|
||||
gArrowWidget);
|
||||
gtk_widget_realize(gArrowWidget);
|
||||
if (!gDropdownEntryWidget) {
|
||||
ensure_entry_widget();
|
||||
gDropdownEntryWidget = gEntryWidget;
|
||||
}
|
||||
|
||||
if (gDropdownButtonWidget) {
|
||||
/* Get the Arrow inside the Button */
|
||||
buttonChild = GTK_BIN(gDropdownButtonWidget)->child;
|
||||
if (GTK_IS_HBOX(buttonChild)) {
|
||||
/* appears-as-list = FALSE, cell-view = TRUE; the button
|
||||
* contains an hbox. This hbox is there because ComboBoxEntry
|
||||
* inherits from ComboBox which needs to place a cell renderer,
|
||||
* a separator, and an arrow in the button when appears-as-list
|
||||
* is FALSE. Here the hbox should only contain an arrow, since
|
||||
* a ComboBoxEntry doesn't need all those widgets in the
|
||||
* button. */
|
||||
gtk_container_forall(GTK_CONTAINER(buttonChild),
|
||||
moz_gtk_get_combo_box_entry_arrow,
|
||||
NULL);
|
||||
} else if(GTK_IS_ARROW(buttonChild)) {
|
||||
/* appears-as-list = TRUE, or cell-view = FALSE;
|
||||
* the button only contains an arrow */
|
||||
gArrowWidget = buttonChild;
|
||||
g_object_add_weak_pointer(G_OBJECT(buttonChild),
|
||||
(gpointer) &gArrowWidget);
|
||||
gtk_widget_realize(gArrowWidget);
|
||||
}
|
||||
} else {
|
||||
/* Shouldn't be reached with current internal gtk implementation;
|
||||
* we use a generic toggle button as last resort fallback to avoid
|
||||
* crashing. */
|
||||
ensure_toggle_button_widget();
|
||||
gDropdownButtonWidget = gToggleButtonWidget;
|
||||
}
|
||||
|
||||
if (!gArrowWidget) {
|
||||
/* Shouldn't be reached with current internal gtk implementation;
|
||||
* we use a generic down arrow as last resort fallback to avoid
|
||||
* crashing. */
|
||||
gArrowWidget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
|
||||
setup_widget_prototype(gArrowWidget);
|
||||
}
|
||||
}
|
||||
return MOZ_GTK_SUCCESS;
|
||||
}
|
||||
|
||||
/* Will go away when bug 416003 lands (Use different arrow widgets for
|
||||
* arrows in different context) */
|
||||
static gint
|
||||
ensure_arrow_widget()
|
||||
{
|
||||
if (!gArrowWidget)
|
||||
ensure_combo_box_entry_widgets();
|
||||
return MOZ_GTK_SUCCESS;
|
||||
}
|
||||
|
||||
static gint
|
||||
ensure_handlebox_widget()
|
||||
{
|
||||
|
@ -675,6 +742,8 @@ moz_gtk_init()
|
|||
have_menu_shadow_type =
|
||||
(gtk_major_version > 2 ||
|
||||
(gtk_major_version == 2 && gtk_minor_version >= 1));
|
||||
have_arrow_scaling = (gtk_major_version > 2 ||
|
||||
(gtk_major_version == 2 && gtk_minor_version >= 12));
|
||||
|
||||
return MOZ_GTK_SUCCESS;
|
||||
}
|
||||
|
@ -854,20 +923,28 @@ moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect,
|
|||
}
|
||||
|
||||
static gint
|
||||
calculate_arrow_dimensions(GdkRectangle* rect, GdkRectangle* arrow_rect)
|
||||
calculate_arrow_dimensions(GdkRectangle* rect, GdkRectangle* arrow_rect,
|
||||
GtkTextDirection direction)
|
||||
{
|
||||
/* defined in gtkarrow.c */
|
||||
gfloat arrow_scaling = 0.7;
|
||||
gfloat xalign, xpad;
|
||||
gint extent;
|
||||
GtkMisc* misc = GTK_MISC(gArrowWidget);
|
||||
|
||||
gint extent = MIN(rect->width - misc->xpad * 2,
|
||||
rect->height - misc->ypad * 2);
|
||||
if (have_arrow_scaling)
|
||||
gtk_widget_style_get(gArrowWidget,
|
||||
"arrow_scaling", &arrow_scaling, NULL);
|
||||
extent = MIN((rect->width - misc->xpad * 2),
|
||||
(rect->height - misc->ypad * 2)) * arrow_scaling;
|
||||
|
||||
arrow_rect->x = ((rect->x + misc->xpad) * (1.0 - misc->xalign) +
|
||||
(rect->x + rect->width - extent - misc->xpad) *
|
||||
misc->xalign);
|
||||
xalign = direction == GTK_TEXT_DIR_LTR ? misc->xalign : 1.0 - misc->xalign;
|
||||
xpad = misc->xpad + (rect->width - extent) * xalign;
|
||||
|
||||
arrow_rect->y = ((rect->y + misc->ypad) * (1.0 - misc->yalign) +
|
||||
(rect->y + rect->height - extent - misc->ypad) *
|
||||
misc->yalign);
|
||||
arrow_rect->x = direction == GTK_TEXT_DIR_LTR ?
|
||||
floor(rect->x + xpad) : ceil(rect->x + xpad);
|
||||
arrow_rect->y = floor(rect->y + misc->ypad +
|
||||
((rect->height - extent) * misc->yalign));
|
||||
|
||||
arrow_rect->width = arrow_rect->height = extent;
|
||||
|
||||
|
@ -883,11 +960,11 @@ moz_gtk_scrollbar_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
|
|||
GtkStateType state_type = ConvertGtkState(state);
|
||||
GtkShadowType shadow_type = (state->active) ?
|
||||
GTK_SHADOW_IN : GTK_SHADOW_OUT;
|
||||
GdkRectangle button_rect;
|
||||
GdkRectangle arrow_rect;
|
||||
GtkStyle* style;
|
||||
GtkWidget *scrollbar;
|
||||
GtkArrowType arrow_type;
|
||||
gint arrow_displacement_x, arrow_displacement_y;
|
||||
const char* detail = (flags & MOZ_GTK_STEPPER_VERTICAL) ?
|
||||
"vscrollbar" : "hscrollbar";
|
||||
|
||||
|
@ -940,20 +1017,26 @@ moz_gtk_scrollbar_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
|
|||
|
||||
style = scrollbar->style;
|
||||
|
||||
ensure_arrow_widget();
|
||||
|
||||
calculate_arrow_dimensions(rect, &button_rect);
|
||||
TSOffsetStyleGCs(style, button_rect.x, button_rect.y);
|
||||
TSOffsetStyleGCs(style, rect->x, rect->y);
|
||||
|
||||
gtk_paint_box(style, drawable, state_type, shadow_type, cliprect,
|
||||
scrollbar, detail, button_rect.x, button_rect.y,
|
||||
button_rect.width, button_rect.height);
|
||||
scrollbar, detail, rect->x, rect->y,
|
||||
rect->width, rect->height);
|
||||
|
||||
arrow_rect.width = button_rect.width / 2;
|
||||
arrow_rect.height = button_rect.height / 2;
|
||||
arrow_rect.x = button_rect.x + (button_rect.width - arrow_rect.width) / 2;
|
||||
arrow_rect.y = button_rect.y +
|
||||
(button_rect.height - arrow_rect.height) / 2;
|
||||
arrow_rect.width = rect->width / 2;
|
||||
arrow_rect.height = rect->height / 2;
|
||||
arrow_rect.x = rect->x + (rect->width - arrow_rect.width) / 2;
|
||||
arrow_rect.y = rect->y + (rect->height - arrow_rect.height) / 2;
|
||||
|
||||
if (state_type == GTK_STATE_ACTIVE) {
|
||||
gtk_widget_style_get(scrollbar,
|
||||
"arrow-displacement-x", &arrow_displacement_x,
|
||||
"arrow-displacement-y", &arrow_displacement_y,
|
||||
NULL);
|
||||
|
||||
arrow_rect.x += arrow_displacement_x;
|
||||
arrow_rect.y += arrow_displacement_y;
|
||||
}
|
||||
|
||||
gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
|
||||
scrollbar, detail, arrow_type, TRUE, arrow_rect.x,
|
||||
|
@ -1578,16 +1661,16 @@ moz_gtk_dropdown_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
|
|||
GdkRectangle* cliprect, GtkWidgetState* state,
|
||||
gboolean input_focus, GtkTextDirection direction)
|
||||
{
|
||||
const gfloat arrow_scaling = 0.7;
|
||||
gint real_arrow_padding;
|
||||
GtkBorder inner_border;
|
||||
gboolean interior_focus;
|
||||
gint focus_width, focus_pad;
|
||||
gint x_displacement, y_displacement;
|
||||
GdkRectangle arrow_rect, real_arrow_rect;
|
||||
GtkStateType state_type = ConvertGtkState(state);
|
||||
GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
|
||||
GtkStyle* style;
|
||||
|
||||
ensure_arrow_widget();
|
||||
ensure_dropdown_entry_widget();
|
||||
gtk_widget_set_direction(gDropdownButtonWidget, direction);
|
||||
ensure_combo_box_entry_widgets();
|
||||
|
||||
if (input_focus) {
|
||||
/* Some themes draw a complementary focus ring for the dropdown button
|
||||
|
@ -1603,27 +1686,37 @@ moz_gtk_dropdown_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
|
|||
|
||||
/* This mirrors gtkbutton's child positioning */
|
||||
style = gDropdownButtonWidget->style;
|
||||
arrow_rect.x = rect->x + 1 + XTHICKNESS(style);
|
||||
arrow_rect.y = rect->y + 1 + YTHICKNESS(style);
|
||||
arrow_rect.width = MAX(1, rect->width - (arrow_rect.x - rect->x) * 2);
|
||||
arrow_rect.height = MAX(1, rect->height - (arrow_rect.y - rect->y) * 2);
|
||||
|
||||
calculate_arrow_dimensions(&arrow_rect, &real_arrow_rect);
|
||||
moz_gtk_button_get_inner_border(gDropdownButtonWidget, &inner_border);
|
||||
moz_gtk_widget_get_focus(gDropdownButtonWidget, &interior_focus,
|
||||
&focus_width, &focus_pad);
|
||||
|
||||
arrow_rect.x = rect->x + XTHICKNESS(style) + focus_width + focus_pad;
|
||||
arrow_rect.x += direction == GTK_TEXT_DIR_LTR ?
|
||||
inner_border.left : inner_border.right;
|
||||
arrow_rect.y = rect->y + inner_border.top + YTHICKNESS(style) +
|
||||
focus_width + focus_pad;
|
||||
arrow_rect.width = MAX(1, rect->width - inner_border.left -
|
||||
inner_border.right - (XTHICKNESS(style) + focus_pad + focus_width) * 2);
|
||||
arrow_rect.height = MAX(1, rect->height - inner_border.top -
|
||||
inner_border.bottom - (YTHICKNESS(style) + focus_pad + focus_width) * 2);
|
||||
|
||||
if (state_type == GTK_STATE_ACTIVE) {
|
||||
gtk_widget_style_get(gDropdownButtonWidget,
|
||||
"child-displacement-x", &x_displacement,
|
||||
"child-displacement-y", &y_displacement,
|
||||
NULL);
|
||||
arrow_rect.x += x_displacement;
|
||||
arrow_rect.y += y_displacement;
|
||||
}
|
||||
|
||||
calculate_arrow_dimensions(&arrow_rect, &real_arrow_rect, direction);
|
||||
|
||||
style = gArrowWidget->style;
|
||||
TSOffsetStyleGCs(style, real_arrow_rect.x, real_arrow_rect.y);
|
||||
|
||||
real_arrow_rect.width = real_arrow_rect.height =
|
||||
MIN (real_arrow_rect.width, real_arrow_rect.height) * arrow_scaling;
|
||||
|
||||
real_arrow_padding = floor((arrow_rect.width - real_arrow_rect.width) / 2 + 0.5);
|
||||
real_arrow_rect.x = arrow_rect.x + real_arrow_padding;
|
||||
if (direction == GTK_TEXT_DIR_RTL)
|
||||
real_arrow_rect.x = arrow_rect.x + arrow_rect.width -
|
||||
real_arrow_rect.width - real_arrow_padding;
|
||||
real_arrow_rect.y = floor (arrow_rect.y + ((arrow_rect.height - real_arrow_rect.height) / 2) + 0.5);
|
||||
|
||||
gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
|
||||
gDropdownButtonWidget, "arrow", GTK_ARROW_DOWN, TRUE,
|
||||
gArrowWidget, "arrow", GTK_ARROW_DOWN, TRUE,
|
||||
real_arrow_rect.x, real_arrow_rect.y,
|
||||
real_arrow_rect.width, real_arrow_rect.height);
|
||||
|
||||
|
@ -2405,11 +2498,11 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
|
|||
w = gTreeHeaderSortArrowWidget;
|
||||
break;
|
||||
case MOZ_GTK_DROPDOWN_ENTRY:
|
||||
ensure_dropdown_entry_widget();
|
||||
ensure_combo_box_entry_widgets();
|
||||
w = gDropdownEntryWidget;
|
||||
break;
|
||||
case MOZ_GTK_DROPDOWN_ARROW:
|
||||
ensure_arrow_widget();
|
||||
ensure_combo_box_entry_widgets();
|
||||
w = gDropdownButtonWidget;
|
||||
break;
|
||||
case MOZ_GTK_DROPDOWN:
|
||||
|
@ -2578,20 +2671,17 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
|
|||
gint
|
||||
moz_gtk_get_dropdown_arrow_size(gint* width, gint* height)
|
||||
{
|
||||
const gint min_arrow_size = 15;
|
||||
ensure_arrow_widget();
|
||||
|
||||
/*
|
||||
* First get the border of the dropdown arrow, then add in the requested
|
||||
* size of the arrow. Note that the minimum arrow size is fixed at
|
||||
* 15 pixels.
|
||||
*/
|
||||
* We get the requisition of the drop down button, which includes
|
||||
* all padding, border and focus line widths the button uses,
|
||||
* as well as the minimum arrow size and its padding
|
||||
* */
|
||||
GtkRequisition requisition;
|
||||
ensure_combo_box_entry_widgets();
|
||||
|
||||
*width = 2 * (1 + XTHICKNESS(gDropdownButtonWidget->style));
|
||||
*width += min_arrow_size + GTK_MISC(gArrowWidget)->xpad * 2;
|
||||
|
||||
*height = 2 * (1 + YTHICKNESS(gDropdownButtonWidget->style));
|
||||
*height += min_arrow_size + GTK_MISC(gArrowWidget)->ypad * 2;
|
||||
gtk_widget_size_request(gDropdownButtonWidget, &requisition);
|
||||
*width = requisition.width;
|
||||
*height = requisition.height;
|
||||
|
||||
return MOZ_GTK_SUCCESS;
|
||||
}
|
||||
|
@ -2829,7 +2919,7 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable,
|
|||
flags, direction);
|
||||
break;
|
||||
case MOZ_GTK_DROPDOWN_ENTRY:
|
||||
ensure_dropdown_entry_widget();
|
||||
ensure_combo_box_entry_widgets();
|
||||
return moz_gtk_entry_paint(drawable, rect, cliprect, state,
|
||||
gDropdownEntryWidget, direction);
|
||||
break;
|
||||
|
|
|
@ -920,8 +920,9 @@ nsNativeThemeGTK::GetWidgetPadding(nsIDeviceContext* aContext,
|
|||
case NS_THEME_BUTTON_FOCUS:
|
||||
case NS_THEME_TOOLBAR_BUTTON:
|
||||
case NS_THEME_TOOLBAR_DUAL_BUTTON:
|
||||
case NS_THEME_TAB_SCROLLARROW_BACK :
|
||||
case NS_THEME_TAB_SCROLLARROW_BACK:
|
||||
case NS_THEME_TAB_SCROLLARROW_FORWARD:
|
||||
case NS_THEME_DROPDOWN_BUTTON:
|
||||
// Radios and checkboxes return a fixed size in GetMinimumWidgetSize
|
||||
// and have a meaningful baseline, so they can't have
|
||||
// author-specified padding.
|
||||
|
|
Загрузка…
Ссылка в новой задаче