Bug 1958733 - Use non-native GTK tooltip drawing. r=stransky
This looks pretty good, is simpler, and should avoid issues where the CSS colors and the widget colors are out of sync like bug 1958596. Differential Revision: https://phabricator.services.mozilla.com/D244537
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
<script>
|
||||
const NON_CONTENT_ACCESSIBLE_ENV_VARS = [
|
||||
"-moz-gtk-csd-titlebar-radius",
|
||||
"-moz-gtk-csd-tooltip-radius",
|
||||
"-moz-gtk-csd-minimize-button-position",
|
||||
"-moz-gtk-csd-maximize-button-position",
|
||||
"-moz-gtk-csd-close-button-position",
|
||||
|
||||
@@ -142,7 +142,7 @@ macro_rules! lnf_int_variable {
|
||||
}};
|
||||
}
|
||||
|
||||
static CHROME_ENVIRONMENT_VARIABLES: [EnvironmentVariable; 9] = [
|
||||
static CHROME_ENVIRONMENT_VARIABLES: [EnvironmentVariable; 10] = [
|
||||
lnf_int_variable!(
|
||||
atom!("-moz-mac-titlebar-height"),
|
||||
MacTitlebarHeight,
|
||||
@@ -158,6 +158,11 @@ static CHROME_ENVIRONMENT_VARIABLES: [EnvironmentVariable; 9] = [
|
||||
TitlebarRadius,
|
||||
int_pixels
|
||||
),
|
||||
lnf_int_variable!(
|
||||
atom!("-moz-gtk-csd-tooltip-radius"),
|
||||
TooltipRadius,
|
||||
int_pixels
|
||||
),
|
||||
lnf_int_variable!(
|
||||
atom!("-moz-gtk-csd-close-button-position"),
|
||||
GTKCSDCloseButtonPosition,
|
||||
|
||||
@@ -369,48 +369,34 @@ tooltip {
|
||||
max-width: 40em;
|
||||
overflow: clip;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* It's important that these styles are in a UA sheet, because the default
|
||||
* tooltip is native anonymous content
|
||||
*/
|
||||
@media (-moz-platform: linux) {
|
||||
tooltip {
|
||||
padding: 6px 10px; /* Matches Adwaita. */
|
||||
line-height: 1.4; /* For Noto Sans; note that 1.2 may clip descenders. */
|
||||
border: .5px solid color-mix(in srgb, currentColor 60%, transparent);
|
||||
@media (-moz-gtk-csd-transparency-available) {
|
||||
border-radius: env(-moz-gtk-csd-tooltip-radius);
|
||||
}
|
||||
}
|
||||
|
||||
@media (-moz-platform: macos) {
|
||||
tooltip {
|
||||
padding: 2px 6px; /* Matches native metrics. */
|
||||
}
|
||||
}
|
||||
|
||||
@media (-moz-platform: windows) {
|
||||
tooltip {
|
||||
appearance: none;
|
||||
border: 1px solid;
|
||||
}
|
||||
|
||||
/* TODO(emilio): Probably make InfoText/InfoBackground do the right thing and
|
||||
* remove this? */
|
||||
@media not (prefers-contrast) {
|
||||
tooltip {
|
||||
background-color: #f9f9fb;
|
||||
color: black;
|
||||
border-color: #67676c;
|
||||
background-color: light-dark(#f9f9fb, #2b2a33);
|
||||
color: light-dark(black, white);
|
||||
border-color: light-dark(#67676c, #f9f9fb);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
tooltip {
|
||||
background-color: #2b2a33;
|
||||
color: white;
|
||||
border-color: #f9f9fb;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -305,6 +305,9 @@ class LookAndFeel {
|
||||
/** GTK button-to-button spacing in the inline axis */
|
||||
TitlebarButtonSpacing,
|
||||
|
||||
/** GTK tooltip radius */
|
||||
TooltipRadius,
|
||||
|
||||
/**
|
||||
* Corresponding to dynamic-range.
|
||||
* https://drafts.csswg.org/mediaqueries-5/#dynamic-range
|
||||
|
||||
@@ -56,20 +56,6 @@ static gint moz_gtk_get_tab_thickness(GtkStyleContext* style);
|
||||
|
||||
static void Inset(GdkRectangle*, const GtkBorder&);
|
||||
|
||||
static void InsetByMargin(GdkRectangle*, GtkStyleContext* style);
|
||||
|
||||
static void moz_gtk_add_style_margin(GtkStyleContext* style, gint* left,
|
||||
gint* top, gint* right, gint* bottom) {
|
||||
GtkBorder margin;
|
||||
|
||||
gtk_style_context_get_margin(style, gtk_style_context_get_state(style),
|
||||
&margin);
|
||||
*left += margin.left;
|
||||
*right += margin.right;
|
||||
*top += margin.top;
|
||||
*bottom += margin.bottom;
|
||||
}
|
||||
|
||||
static void moz_gtk_add_style_border(GtkStyleContext* style, gint* left,
|
||||
gint* top, gint* right, gint* bottom) {
|
||||
GtkBorder border;
|
||||
@@ -96,14 +82,6 @@ static void moz_gtk_add_style_padding(GtkStyleContext* style, gint* left,
|
||||
*bottom += padding.bottom;
|
||||
}
|
||||
|
||||
static void moz_gtk_add_margin_border_padding(GtkStyleContext* style,
|
||||
gint* left, gint* top,
|
||||
gint* right, gint* bottom) {
|
||||
moz_gtk_add_style_margin(style, left, top, right, bottom);
|
||||
moz_gtk_add_style_border(style, left, top, right, bottom);
|
||||
moz_gtk_add_style_padding(style, left, top, right, bottom);
|
||||
}
|
||||
|
||||
static void moz_gtk_add_border_padding(GtkStyleContext* style, gint* left,
|
||||
gint* top, gint* right, gint* bottom) {
|
||||
moz_gtk_add_style_border(style, left, top, right, bottom);
|
||||
@@ -598,14 +576,6 @@ static void Inset(GdkRectangle* rect, const GtkBorder& aBorder) {
|
||||
rect->height -= aBorder.top + aBorder.bottom;
|
||||
}
|
||||
|
||||
// Inset a rectangle by the margins specified in a style context.
|
||||
static void InsetByMargin(GdkRectangle* rect, GtkStyleContext* style) {
|
||||
GtkBorder margin;
|
||||
gtk_style_context_get_margin(style, gtk_style_context_get_state(style),
|
||||
&margin);
|
||||
Inset(rect, margin);
|
||||
}
|
||||
|
||||
// Inset a rectangle by the border and padding specified in a style context.
|
||||
static void InsetByBorderPadding(GdkRectangle* rect, GtkStyleContext* style) {
|
||||
GtkStateFlags state = gtk_style_context_get_state(style);
|
||||
@@ -617,20 +587,6 @@ static void InsetByBorderPadding(GdkRectangle* rect, GtkStyleContext* style) {
|
||||
Inset(rect, border);
|
||||
}
|
||||
|
||||
static void moz_gtk_draw_styled_frame(GtkStyleContext* style, cairo_t* cr,
|
||||
const GdkRectangle* aRect,
|
||||
bool drawFocus) {
|
||||
GdkRectangle rect = *aRect;
|
||||
|
||||
InsetByMargin(&rect, style);
|
||||
|
||||
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 (drawFocus) {
|
||||
gtk_render_focus(style, cr, rect.x, rect.y, rect.width, rect.height);
|
||||
}
|
||||
}
|
||||
|
||||
/* See gtk_range_draw() for reference.
|
||||
*/
|
||||
static gint moz_gtk_scale_paint(cairo_t* cr, GdkRectangle* rect,
|
||||
@@ -916,54 +872,6 @@ static gint moz_gtk_arrow_paint(cairo_t* cr, GdkRectangle* rect,
|
||||
return MOZ_GTK_SUCCESS;
|
||||
}
|
||||
|
||||
static gint moz_gtk_tooltip_paint(cairo_t* cr, const GdkRectangle* aRect,
|
||||
GtkWidgetState* state,
|
||||
GtkTextDirection direction) {
|
||||
// Tooltip widget is made in GTK3 as following tree:
|
||||
// Tooltip window
|
||||
// Horizontal Box
|
||||
// Icon (not supported by Firefox)
|
||||
// Label
|
||||
// Each element can be fully styled by CSS of GTK theme.
|
||||
// We have to draw all elements with appropriate offset and right dimensions.
|
||||
|
||||
// Tooltip drawing
|
||||
GtkStyleContext* style =
|
||||
GetStyleContext(MOZ_GTK_TOOLTIP, state->image_scale, direction);
|
||||
GdkRectangle rect = *aRect;
|
||||
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);
|
||||
|
||||
// Horizontal Box drawing
|
||||
//
|
||||
// The box element has hard-coded 6px margin-* GtkWidget properties, which
|
||||
// are added between the window dimensions and the CSS margin box of the
|
||||
// horizontal box. The frame of the tooltip window is drawn in the
|
||||
// 6px margin.
|
||||
// For drawing Horizontal Box we have to inset drawing area by that 6px
|
||||
// plus its CSS margin.
|
||||
GtkStyleContext* boxStyle =
|
||||
GetStyleContext(MOZ_GTK_TOOLTIP_BOX, state->image_scale, direction);
|
||||
|
||||
rect.x += 6;
|
||||
rect.y += 6;
|
||||
rect.width -= 12;
|
||||
rect.height -= 12;
|
||||
|
||||
InsetByMargin(&rect, boxStyle);
|
||||
gtk_render_background(boxStyle, cr, rect.x, rect.y, rect.width, rect.height);
|
||||
gtk_render_frame(boxStyle, cr, rect.x, rect.y, rect.width, rect.height);
|
||||
|
||||
// Label drawing
|
||||
InsetByBorderPadding(&rect, boxStyle);
|
||||
|
||||
GtkStyleContext* labelStyle =
|
||||
GetStyleContext(MOZ_GTK_TOOLTIP_BOX_LABEL, state->image_scale, direction);
|
||||
moz_gtk_draw_styled_frame(labelStyle, cr, &rect, false);
|
||||
|
||||
return MOZ_GTK_SUCCESS;
|
||||
}
|
||||
|
||||
static gint moz_gtk_resizer_paint(cairo_t* cr, GdkRectangle* rect,
|
||||
GtkWidgetState* state,
|
||||
GtkTextDirection direction) {
|
||||
@@ -1409,23 +1317,6 @@ gint moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top,
|
||||
case MOZ_GTK_FRAME:
|
||||
w = GetWidget(MOZ_GTK_FRAME);
|
||||
break;
|
||||
case MOZ_GTK_TOOLTIP: {
|
||||
// In GTK 3 there are 6 pixels of additional margin around the box.
|
||||
// See details there:
|
||||
// https://github.com/GNOME/gtk/blob/5ea69a136bd7e4970b3a800390e20314665aaed2/gtk/ui/gtktooltipwindow.ui#L11
|
||||
*left = *right = *top = *bottom = 6;
|
||||
|
||||
// We also need to add margin/padding/borders from Tooltip content.
|
||||
// Tooltip contains horizontal box, where icon and label is put.
|
||||
// We ignore icon as long as we don't have support for it.
|
||||
GtkStyleContext* boxStyle = GetStyleContext(MOZ_GTK_TOOLTIP_BOX);
|
||||
moz_gtk_add_margin_border_padding(boxStyle, left, top, right, bottom);
|
||||
|
||||
GtkStyleContext* labelStyle = GetStyleContext(MOZ_GTK_TOOLTIP_BOX_LABEL);
|
||||
moz_gtk_add_margin_border_padding(labelStyle, left, top, right, bottom);
|
||||
|
||||
return MOZ_GTK_SUCCESS;
|
||||
}
|
||||
/* These widgets have no borders, since they are not containers. */
|
||||
case MOZ_GTK_SPLITTER_HORIZONTAL:
|
||||
case MOZ_GTK_SPLITTER_VERTICAL:
|
||||
@@ -1670,8 +1561,6 @@ gint moz_gtk_widget_paint(WidgetNodeType widget, cairo_t* cr,
|
||||
return moz_gtk_text_view_paint(cr, rect, state, direction);
|
||||
case MOZ_GTK_DROPDOWN:
|
||||
return moz_gtk_combo_box_paint(cr, rect, state, direction);
|
||||
case MOZ_GTK_TOOLTIP:
|
||||
return moz_gtk_tooltip_paint(cr, rect, state, direction);
|
||||
case MOZ_GTK_FRAME:
|
||||
return moz_gtk_frame_paint(cr, rect, state, direction);
|
||||
case MOZ_GTK_RESIZER:
|
||||
|
||||
@@ -1176,6 +1176,11 @@ nsresult nsLookAndFeel::NativeGetInt(IntID aID, int32_t& aResult) {
|
||||
// No GTK API for checking if inverted colors is enabled
|
||||
aResult = 0;
|
||||
break;
|
||||
case IntID::TooltipRadius: {
|
||||
EnsureInit();
|
||||
aResult = EffectiveTheme().mTooltipRadius;
|
||||
break;
|
||||
}
|
||||
case IntID::TitlebarRadius: {
|
||||
EnsureInit();
|
||||
aResult = EffectiveTheme().mTitlebarRadius;
|
||||
@@ -2100,6 +2105,7 @@ void nsLookAndFeel::PerThemeData::Init() {
|
||||
mInfo.mFg = GetTextColor(style);
|
||||
style = GetStyleContext(MOZ_GTK_TOOLTIP);
|
||||
mInfo.mBg = GetBackgroundColor(style, mInfo.mFg);
|
||||
mTooltipRadius = GetBorderRadius(style);
|
||||
|
||||
style = GetStyleContext(MOZ_GTK_MENUITEM);
|
||||
{
|
||||
|
||||
@@ -167,6 +167,7 @@ class nsLookAndFeel final : public nsXPLookAndFeel {
|
||||
|
||||
float mCaretRatio = 0.0f;
|
||||
int32_t mTitlebarRadius = 0;
|
||||
int32_t mTooltipRadius = 0;
|
||||
int32_t mTitlebarButtonSpacing = 0;
|
||||
char16_t mInvisibleCharacter = 0;
|
||||
bool mMenuSupportsDrag = false;
|
||||
|
||||
@@ -291,9 +291,6 @@ bool nsNativeThemeGTK::GetGtkWidgetAndState(StyleAppearance aAppearance,
|
||||
*aWidgetFlags = GTK_ARROW_LEFT;
|
||||
}
|
||||
break;
|
||||
case StyleAppearance::Tooltip:
|
||||
aGtkWidgetType = MOZ_GTK_TOOLTIP;
|
||||
break;
|
||||
case StyleAppearance::ProgressBar:
|
||||
aGtkWidgetType = MOZ_GTK_PROGRESSBAR;
|
||||
break;
|
||||
@@ -868,7 +865,6 @@ bool nsNativeThemeGTK::GetWidgetPadding(nsDeviceContext* aContext,
|
||||
}
|
||||
switch (aAppearance) {
|
||||
case StyleAppearance::Toolbarbutton:
|
||||
case StyleAppearance::Tooltip:
|
||||
case StyleAppearance::MozWindowButtonClose:
|
||||
case StyleAppearance::MozWindowButtonMinimize:
|
||||
case StyleAppearance::MozWindowButtonMaximize:
|
||||
@@ -919,21 +915,6 @@ auto nsNativeThemeGTK::IsWidgetNonNative(nsIFrame* aFrame,
|
||||
return NonNative::No;
|
||||
}
|
||||
|
||||
// As an special-case, for tooltips, we check if the tooltip color is the
|
||||
// same between the light and dark themes. If so we can get away with drawing
|
||||
// the native widget, see bug 1817396.
|
||||
if (aAppearance == StyleAppearance::Tooltip) {
|
||||
auto darkColor =
|
||||
LookAndFeel::Color(StyleSystemColor::Infotext, ColorScheme::Dark,
|
||||
LookAndFeel::UseStandins::No);
|
||||
auto lightColor =
|
||||
LookAndFeel::Color(StyleSystemColor::Infotext, ColorScheme::Light,
|
||||
LookAndFeel::UseStandins::No);
|
||||
if (darkColor == lightColor) {
|
||||
return NonNative::No;
|
||||
}
|
||||
}
|
||||
|
||||
// If the non-native theme doesn't support the widget then oh well...
|
||||
if (!Theme::ThemeSupportsWidget(aFrame->PresContext(), aFrame, aAppearance)) {
|
||||
return NonNative::No;
|
||||
@@ -1068,7 +1049,6 @@ bool nsNativeThemeGTK::WidgetAttributeChangeRequiresRepaint(
|
||||
// Some widget types just never change state.
|
||||
if (aAppearance == StyleAppearance::Progresschunk ||
|
||||
aAppearance == StyleAppearance::ProgressBar ||
|
||||
aAppearance == StyleAppearance::Tooltip ||
|
||||
aAppearance == StyleAppearance::MozWindowDecorations) {
|
||||
return false;
|
||||
}
|
||||
@@ -1117,7 +1097,6 @@ nsNativeThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext,
|
||||
case StyleAppearance::Tab:
|
||||
// case StyleAppearance::Tabpanel:
|
||||
case StyleAppearance::Tabpanels:
|
||||
case StyleAppearance::Tooltip:
|
||||
case StyleAppearance::NumberInput:
|
||||
case StyleAppearance::PasswordInput:
|
||||
case StyleAppearance::Textfield:
|
||||
@@ -1178,15 +1157,8 @@ nsITheme::Transparency nsNativeThemeGTK::GetWidgetTransparency(
|
||||
return Theme::GetWidgetTransparency(aFrame, aAppearance);
|
||||
}
|
||||
|
||||
switch (aAppearance) {
|
||||
// Tooltips use gtk_paint_flat_box() on Gtk2
|
||||
// but are shaped on Gtk3
|
||||
case StyleAppearance::Tooltip:
|
||||
return eTransparent;
|
||||
default:
|
||||
return eUnknownTransparency;
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<Theme> do_CreateNativeThemeDoNotUseDirectly() {
|
||||
if (gfxPlatform::IsHeadless()) {
|
||||
|
||||
@@ -158,6 +158,7 @@ static const char sIntPrefs[][45] = {
|
||||
"ui.touchDeviceSupportPresent",
|
||||
"ui.titlebarRadius",
|
||||
"ui.titlebarButtonSpacing",
|
||||
"ui.tooltipRadius",
|
||||
"ui.dynamicRange",
|
||||
"ui.panelAnimations",
|
||||
"ui.hideCursorWhileTyping",
|
||||
|
||||
@@ -2293,6 +2293,7 @@ STATIC_ATOMS = [
|
||||
Atom("_moz_gtk_csd_available", "-moz-gtk-csd-available"),
|
||||
Atom("_moz_gtk_csd_transparency_available", "-moz-gtk-csd-transparency-available"),
|
||||
Atom("_moz_gtk_csd_titlebar_radius", "-moz-gtk-csd-titlebar-radius"),
|
||||
Atom("_moz_gtk_csd_tooltip_radius", "-moz-gtk-csd-tooltip-radius"),
|
||||
Atom("_moz_gtk_csd_titlebar_button_spacing", "-moz-gtk-csd-titlebar-button-spacing"),
|
||||
Atom("_moz_gtk_csd_minimize_button", "-moz-gtk-csd-minimize-button"),
|
||||
Atom("_moz_gtk_csd_minimize_button_position", "-moz-gtk-csd-minimize-button-position"),
|
||||
|
||||
Reference in New Issue
Block a user