summaryrefslogtreecommitdiff
path: root/mozilla-1073117-no-gap-tab.patch
diff options
context:
space:
mode:
Diffstat (limited to 'mozilla-1073117-no-gap-tab.patch')
-rw-r--r--mozilla-1073117-no-gap-tab.patch463
1 files changed, 463 insertions, 0 deletions
diff --git a/mozilla-1073117-no-gap-tab.patch b/mozilla-1073117-no-gap-tab.patch
new file mode 100644
index 0000000..2ca16c7
--- /dev/null
+++ b/mozilla-1073117-no-gap-tab.patch
@@ -0,0 +1,463 @@
+diff --git a/widget/gtk/gtk3drawing.c b/widget/gtk/gtk3drawing.c
+--- a/widget/gtk/gtk3drawing.c
++++ b/widget/gtk/gtk3drawing.c
+@@ -2098,18 +2098,23 @@ moz_gtk_progress_chunk_paint(cairo_t *cr
+ return MOZ_GTK_SUCCESS;
+ }
+
+ gint
+ moz_gtk_get_tab_thickness(void)
+ {
+ GtkBorder border;
+ GtkStyleContext * style;
++ gboolean has_tab_gap;
+
+ ensure_tab_widget();
++ gtk_widget_style_get(gTabWidget, "has-tab-gap", &has_tab_gap, NULL);
++ if (!has_tab_gap)
++ return 0; /* don't use ythickness for tabs without a gap */
++
+ style = gtk_widget_get_style_context(gTabWidget);
+ gtk_style_context_add_class(style, GTK_STYLE_CLASS_NOTEBOOK);
+ gtk_style_context_get_border(style, 0, &border);
+
+ if (border.top < 2)
+ return 2; /* some themes don't set ythickness correctly */
+
+ return border.top;
+@@ -2140,172 +2145,196 @@ moz_gtk_tab_paint(cairo_t *cr, GdkRectan
+ * When it is selected, we overwrite the adjacent border of the tabpanel
+ * touching the tab with a pierced border (called "the gap") to make the
+ * tab appear physically attached to the tabpanel; see details below. */
+
+ GtkStyleContext* style;
+ GdkRectangle tabRect;
+ GdkRectangle focusRect;
+ GdkRectangle backRect;
++ gboolean has_tab_gap;
+ int initial_gap = 0;
+
+ ensure_tab_widget();
+ gtk_widget_set_direction(gTabWidget, direction);
+
+ style = gtk_widget_get_style_context(gTabWidget);
+ gtk_style_context_save(style);
+ moz_gtk_tab_prepare_style_context(style, flags);
+
+- tabRect = *rect;
+-
+- if (flags & MOZ_GTK_TAB_FIRST) {
+- gtk_widget_style_get (gTabWidget, "initial-gap", &initial_gap, NULL);
+- tabRect.width -= initial_gap;
+-
+- if (direction != GTK_TEXT_DIR_RTL) {
+- tabRect.x += initial_gap;
++ gtk_widget_style_get(gTabWidget, "has-tab-gap", &has_tab_gap, NULL);
++ if (has_tab_gap) {
++ tabRect = *rect;
++ if (flags & MOZ_GTK_TAB_FIRST) {
++ gtk_widget_style_get (gTabWidget, "initial-gap", &initial_gap, NULL);
++ tabRect.width -= initial_gap;
++
++ if (direction != GTK_TEXT_DIR_RTL) {
++ tabRect.x += initial_gap;
++ }
+ }
+- }
+-
+- focusRect = backRect = tabRect;
+-
+- if ((flags & MOZ_GTK_TAB_SELECTED) == 0) {
+- /* Only draw the tab */
+- gtk_render_extension(style, cr,
+- tabRect.x, tabRect.y, tabRect.width, tabRect.height,
+- (flags & MOZ_GTK_TAB_BOTTOM) ?
+- GTK_POS_TOP : GTK_POS_BOTTOM );
++
++ focusRect = backRect = tabRect;
++
++ if ((flags & MOZ_GTK_TAB_SELECTED) == 0) {
++ /* Only draw the tab */
++ gtk_render_extension(style, cr,
++ tabRect.x, tabRect.y, tabRect.width, tabRect.height,
++ (flags & MOZ_GTK_TAB_BOTTOM) ?
++ GTK_POS_TOP : GTK_POS_BOTTOM );
++ } else {
++ /* Draw the tab and the gap
++ * We want the gap to be positioned exactly on the tabpanel top
++ * border; since tabbox.css may set a negative margin so that the tab
++ * frame rect already overlaps the tabpanel frame rect, we need to take
++ * that into account when drawing. To that effect, nsNativeThemeGTK
++ * passes us this negative margin (bmargin in the graphic below) in the
++ * lowest bits of |flags|. We use it to set gap_voffset, the distance
++ * between the top of the gap and the bottom of the tab (resp. the
++ * bottom of the gap and the top of the tab when we draw a bottom tab),
++ * while ensuring that the gap always touches the border of the tab,
++ * i.e. 0 <= gap_voffset <= gap_height, to avoid surprinsing results
++ * with big negative or positive margins.
++ * Here is a graphical explanation in the case of top tabs:
++ * ___________________________
++ * / \
++ * | T A B |
++ * ----------|. . . . . . . . . . . . . . .|----- top of tabpanel
++ * : ^ bmargin : ^
++ * : | (-negative margin, : |
++ * bottom : v passed in flags) : | gap_height
++ * of -> :.............................: | (the size of the
++ * the tab . part of the gap . | tabpanel top border)
++ * . outside of the tab . v
++ * ----------------------------------------------
++ *
++ * To draw the gap, we use gtk_paint_box_gap(), see comment in
++ * moz_gtk_tabpanels_paint(). This box_gap is made 3 * gap_height tall,
++ * which should suffice to ensure that the only visible border is the
++ * pierced one. If the tab is in the middle, we make the box_gap begin
++ * a bit to the left of the tab and end a bit to the right, adjusting
++ * the gap position so it still is under the tab, because we want the
++ * rendering of a gap in the middle of a tabpanel. This is the role of
++ * the gints gap_{l,r}_offset. On the contrary, if the tab is the
++ * first, we align the start border of the box_gap with the start
++ * border of the tab (left if LTR, right if RTL), by setting the
++ * appropriate offset to 0.*/
++ gint gap_loffset, gap_roffset, gap_voffset, gap_height;
++
++ /* Get height needed by the gap */
++ gap_height = moz_gtk_get_tab_thickness();
++
++ /* Extract gap_voffset from the first bits of flags */
++ gap_voffset = flags & MOZ_GTK_TAB_MARGIN_MASK;
++ if (gap_voffset > gap_height)
++ gap_voffset = gap_height;
++
++ /* Set gap_{l,r}_offset to appropriate values */
++ gap_loffset = gap_roffset = 20; /* should be enough */
++ if (flags & MOZ_GTK_TAB_FIRST) {
++ if (direction == GTK_TEXT_DIR_RTL)
++ gap_roffset = initial_gap;
++ else
++ gap_loffset = initial_gap;
++ }
++
++ if (flags & MOZ_GTK_TAB_BOTTOM) {
++ /* Draw the tab on bottom */
++ focusRect.y += gap_voffset;
++ focusRect.height -= gap_voffset;
++
++ gtk_render_extension(style, cr,
++ tabRect.x, tabRect.y + gap_voffset, tabRect.width,
++ tabRect.height - gap_voffset, GTK_POS_TOP);
++
++ gtk_style_context_remove_region(style, GTK_STYLE_REGION_TAB);
++
++ backRect.y += (gap_voffset - gap_height);
++ backRect.height = gap_height;
++
++ /* Draw the gap; erase with background color before painting in
++ * case theme does not */
++ gtk_render_background(style, cr, backRect.x, backRect.y,
++ backRect.width, backRect.height);
++ cairo_save(cr);
++ cairo_rectangle(cr, backRect.x, backRect.y, backRect.width, backRect.height);
++ cairo_clip(cr);
++
++ gtk_render_frame_gap(style, cr,
++ tabRect.x - gap_loffset,
++ tabRect.y + gap_voffset - 3 * gap_height,
++ tabRect.width + gap_loffset + gap_roffset,
++ 3 * gap_height, GTK_POS_BOTTOM,
++ gap_loffset, gap_loffset + tabRect.width);
++ cairo_restore(cr);
++ } else {
++ /* Draw the tab on top */
++ focusRect.height -= gap_voffset;
++ gtk_render_extension(style, cr,
++ tabRect.x, tabRect.y, tabRect.width,
++ tabRect.height - gap_voffset, GTK_POS_BOTTOM);
++
++ gtk_style_context_remove_region(style, GTK_STYLE_REGION_TAB);
++
++ backRect.y += (tabRect.height - gap_voffset);
++ backRect.height = gap_height;
++
++ /* Draw the gap; erase with background color before painting in
++ * case theme does not */
++ gtk_render_background(style, cr, backRect.x, backRect.y,
++ backRect.width, backRect.height);
++
++ cairo_save(cr);
++ cairo_rectangle(cr, backRect.x, backRect.y, backRect.width, backRect.height);
++ cairo_clip(cr);
++
++ gtk_render_frame_gap(style, cr,
++ tabRect.x - gap_loffset,
++ tabRect.y + tabRect.height - gap_voffset,
++ tabRect.width + gap_loffset + gap_roffset,
++ 3 * gap_height, GTK_POS_TOP,
++ gap_loffset, gap_loffset + tabRect.width);
++ cairo_restore(cr);
++ }
++
++ if (state->focused) {
++ /* Paint the focus ring */
++ GtkBorder border;
++ gtk_style_context_get_border(style, GetStateFlagsFromGtkWidgetState(state), &border);
++
++ focusRect.x += border.left;
++ focusRect.width -= (border.left + border.right);
++ focusRect.y += border.top;
++ focusRect.height -= (border.top + border.bottom);
++
++ gtk_render_focus(style, cr,
++ focusRect.x, focusRect.y, focusRect.width, focusRect.height);
++ }
++ }
+ } else {
+- /* Draw the tab and the gap
+- * We want the gap to be positioned exactly on the tabpanel top
+- * border; since tabbox.css may set a negative margin so that the tab
+- * frame rect already overlaps the tabpanel frame rect, we need to take
+- * that into account when drawing. To that effect, nsNativeThemeGTK
+- * passes us this negative margin (bmargin in the graphic below) in the
+- * lowest bits of |flags|. We use it to set gap_voffset, the distance
+- * between the top of the gap and the bottom of the tab (resp. the
+- * bottom of the gap and the top of the tab when we draw a bottom tab),
+- * while ensuring that the gap always touches the border of the tab,
+- * i.e. 0 <= gap_voffset <= gap_height, to avoid surprinsing results
+- * with big negative or positive margins.
+- * Here is a graphical explanation in the case of top tabs:
+- * ___________________________
+- * / \
+- * | T A B |
+- * ----------|. . . . . . . . . . . . . . .|----- top of tabpanel
+- * : ^ bmargin : ^
+- * : | (-negative margin, : |
+- * bottom : v passed in flags) : | gap_height
+- * of -> :.............................: | (the size of the
+- * the tab . part of the gap . | tabpanel top border)
+- * . outside of the tab . v
+- * ----------------------------------------------
+- *
+- * To draw the gap, we use gtk_paint_box_gap(), see comment in
+- * moz_gtk_tabpanels_paint(). This box_gap is made 3 * gap_height tall,
+- * which should suffice to ensure that the only visible border is the
+- * pierced one. If the tab is in the middle, we make the box_gap begin
+- * a bit to the left of the tab and end a bit to the right, adjusting
+- * the gap position so it still is under the tab, because we want the
+- * rendering of a gap in the middle of a tabpanel. This is the role of
+- * the gints gap_{l,r}_offset. On the contrary, if the tab is the
+- * first, we align the start border of the box_gap with the start
+- * border of the tab (left if LTR, right if RTL), by setting the
+- * appropriate offset to 0.*/
+- gint gap_loffset, gap_roffset, gap_voffset, gap_height;
+-
+- /* Get height needed by the gap */
+- gap_height = moz_gtk_get_tab_thickness();
+-
+- /* Extract gap_voffset from the first bits of flags */
+- gap_voffset = flags & MOZ_GTK_TAB_MARGIN_MASK;
+- if (gap_voffset > gap_height)
+- gap_voffset = gap_height;
+-
+- /* Set gap_{l,r}_offset to appropriate values */
+- gap_loffset = gap_roffset = 20; /* should be enough */
+- if (flags & MOZ_GTK_TAB_FIRST) {
+- if (direction == GTK_TEXT_DIR_RTL)
+- gap_roffset = initial_gap;
+- else
+- gap_loffset = initial_gap;
++ gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height);
++ gtk_render_frame(style, cr, rect->x, rect->y,rect->width, rect->height);
++
++ if (state->focused) {
++ /* Paint the focus ring */
++ GtkBorder padding;
++
++ GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
++
++ focusRect = *rect;
++ gtk_style_context_get_padding(style, state_flags, &padding);
++
++ focusRect.x += padding.left;
++ focusRect.width -= (padding.left + padding.right);
++ focusRect.y += padding.top;
++ focusRect.height -= (padding.top + padding.bottom);
++
++ gtk_render_focus(style, cr,
++ focusRect.x, focusRect.y, focusRect.width, focusRect.height);
+ }
+-
+- if (flags & MOZ_GTK_TAB_BOTTOM) {
+- /* Draw the tab on bottom */
+- focusRect.y += gap_voffset;
+- focusRect.height -= gap_voffset;
+-
+- gtk_render_extension(style, cr,
+- tabRect.x, tabRect.y + gap_voffset, tabRect.width,
+- tabRect.height - gap_voffset, GTK_POS_TOP);
+-
+- gtk_style_context_remove_region(style, GTK_STYLE_REGION_TAB);
+-
+- backRect.y += (gap_voffset - gap_height);
+- backRect.height = gap_height;
+-
+- /* Draw the gap; erase with background color before painting in
+- * case theme does not */
+- gtk_render_background(style, cr, backRect.x, backRect.y,
+- backRect.width, backRect.height);
+- cairo_save(cr);
+- cairo_rectangle(cr, backRect.x, backRect.y, backRect.width, backRect.height);
+- cairo_clip(cr);
+-
+- gtk_render_frame_gap(style, cr,
+- tabRect.x - gap_loffset,
+- tabRect.y + gap_voffset - 3 * gap_height,
+- tabRect.width + gap_loffset + gap_roffset,
+- 3 * gap_height, GTK_POS_BOTTOM,
+- gap_loffset, gap_loffset + tabRect.width);
+- cairo_restore(cr);
+- } else {
+- /* Draw the tab on top */
+- focusRect.height -= gap_voffset;
+- gtk_render_extension(style, cr,
+- tabRect.x, tabRect.y, tabRect.width,
+- tabRect.height - gap_voffset, GTK_POS_BOTTOM);
+-
+- gtk_style_context_remove_region(style, GTK_STYLE_REGION_TAB);
+-
+- backRect.y += (tabRect.height - gap_voffset);
+- backRect.height = gap_height;
+-
+- /* Draw the gap; erase with background color before painting in
+- * case theme does not */
+- gtk_render_background(style, cr, backRect.x, backRect.y,
+- backRect.width, backRect.height);
+-
+- cairo_save(cr);
+- cairo_rectangle(cr, backRect.x, backRect.y, backRect.width, backRect.height);
+- cairo_clip(cr);
+-
+- gtk_render_frame_gap(style, cr,
+- tabRect.x - gap_loffset,
+- tabRect.y + tabRect.height - gap_voffset,
+- tabRect.width + gap_loffset + gap_roffset,
+- 3 * gap_height, GTK_POS_TOP,
+- gap_loffset, gap_loffset + tabRect.width);
+- cairo_restore(cr);
+- }
+- }
+-
+- if (state->focused) {
+- /* Paint the focus ring */
+- GtkBorder border;
+- gtk_style_context_get_border(style, GetStateFlagsFromGtkWidgetState(state), &border);
+-
+- focusRect.x += border.left;
+- focusRect.width -= (border.left + border.right);
+- focusRect.y += border.top;
+- focusRect.height -= (border.top + border.bottom);
+-
+- gtk_render_focus(style, cr,
+- focusRect.x, focusRect.y, focusRect.width, focusRect.height);
+ }
+
+ gtk_style_context_restore(style);
+
+ return MOZ_GTK_SUCCESS;
+ }
+
+ /* tab area*/
+@@ -2963,48 +2992,53 @@ moz_gtk_get_widget_border(GtkThemeWidget
+ }
+
+ gint
+ moz_gtk_get_tab_border(gint* left, gint* top, gint* right, gint* bottom,
+ GtkTextDirection direction, GtkTabFlags flags)
+ {
+ GtkStyleContext* style;
+ int tab_curvature;
++ gboolean has_tab_gap;
+
+ ensure_tab_widget();
+
+ style = gtk_widget_get_style_context(gTabWidget);
+ gtk_style_context_save(style);
+ moz_gtk_tab_prepare_style_context(style, flags);
+
+ // TODO add_style_border() should be replaced
+ // with focus-line-width and focus-padding
+ // see Bug 877605
+ *left = *top = *right = *bottom = 0;
+- moz_gtk_add_style_border(style, left, top, right, bottom);
+ moz_gtk_add_style_padding(style, left, top, right, bottom);
+
+- gtk_widget_style_get (gTabWidget, "tab-curvature", &tab_curvature, NULL);
+- *left += tab_curvature;
+- *right += tab_curvature;
+-
+- if (flags & MOZ_GTK_TAB_FIRST) {
+- int initial_gap;
+- gtk_widget_style_get (gTabWidget, "initial-gap", &initial_gap, NULL);
+- if (direction == GTK_TEXT_DIR_RTL)
+- *right += initial_gap;
+- else
+- *left += initial_gap;
+- }
+-
+- // Top tabs have no bottom border, bottom tabs have no top border
+- if (flags & MOZ_GTK_TAB_BOTTOM) {
+- *top = 0;
+- } else {
+- *bottom = 0;
++ gtk_widget_style_get(gTabWidget, "has-tab-gap", &has_tab_gap, NULL);
++ if (has_tab_gap) {
++ moz_gtk_add_style_border(style, left, top, right, bottom);
++
++ gtk_widget_style_get (gTabWidget, "tab-curvature", &tab_curvature, NULL);
++ *left += tab_curvature;
++ *right += tab_curvature;
++
++ if (flags & MOZ_GTK_TAB_FIRST) {
++ int initial_gap;
++ gtk_widget_style_get (gTabWidget, "initial-gap", &initial_gap, NULL);
++ if (direction == GTK_TEXT_DIR_RTL)
++ *right += initial_gap;
++ else
++ *left += initial_gap;
++ }
++
++ // Top tabs have no bottom border, bottom tabs have no top border
++ if (flags & MOZ_GTK_TAB_BOTTOM) {
++ *top = 0;
++ } else {
++ *bottom = 0;
++ }
+ }
+
+ gtk_style_context_restore(style);
+
+ return MOZ_GTK_SUCCESS;
+ }
+
+ gint
+diff --git a/widget/gtk/nsNativeThemeGTK.cpp b/widget/gtk/nsNativeThemeGTK.cpp
+--- a/widget/gtk/nsNativeThemeGTK.cpp
++++ b/widget/gtk/nsNativeThemeGTK.cpp
+@@ -756,16 +756,18 @@ nsNativeThemeGTK::GetExtraSizeForWidget(
+ return true;
+ }
+ case NS_THEME_TAB :
+ {
+ if (!IsSelectedTab(aFrame))
+ return false;
+
+ gint gap_height = moz_gtk_get_tab_thickness();
++ if (!gap_height)
++ return false;
+
+ int32_t extra = gap_height - GetTabMarginPixels(aFrame);
+ if (extra <= 0)
+ return false;
+
+ if (IsBottomTab(aFrame)) {
+ aExtra->top = extra;
+ } else {
bgstack15