mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-03 18:47:53 +00:00
Bug 1737676 - Use GTK menu radius on native context menus and panels. r=stransky
Differential Revision: https://phabricator.services.mozilla.com/D129439
This commit is contained in:
parent
6f11994c29
commit
5b31eea4fd
@ -75,8 +75,13 @@ fn get_titlebar_radius(device: &Device) -> VariableValue {
|
||||
VariableValue::pixel(device.titlebar_radius())
|
||||
}
|
||||
|
||||
static CHROME_ENVIRONMENT_VARIABLES: [EnvironmentVariable; 1] = [
|
||||
fn get_menu_radius(device: &Device) -> VariableValue {
|
||||
VariableValue::pixel(device.menu_radius())
|
||||
}
|
||||
|
||||
static CHROME_ENVIRONMENT_VARIABLES: [EnvironmentVariable; 2] = [
|
||||
make_variable!(atom!("-moz-gtk-csd-titlebar-radius"), get_titlebar_radius),
|
||||
make_variable!(atom!("-moz-gtk-menu-radius"), get_menu_radius),
|
||||
];
|
||||
|
||||
impl CssEnvironment {
|
||||
|
@ -375,6 +375,13 @@ impl Device {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the gtk menu radius in CSS pixels.
|
||||
pub fn menu_radius(&self) -> f32 {
|
||||
unsafe {
|
||||
bindings::Gecko_GetLookAndFeelInt(bindings::LookAndFeel_IntID::GtkMenuRadius as i32) as f32
|
||||
}
|
||||
}
|
||||
|
||||
/// Return whether the document is a chrome document.
|
||||
#[inline]
|
||||
pub fn is_chrome_document(&self) -> bool {
|
||||
|
@ -10,10 +10,10 @@
|
||||
menupopup,
|
||||
panel {
|
||||
min-width: 1px;
|
||||
--panel-padding: 0;
|
||||
--panel-padding: max(env(-moz-gtk-menu-radius) - 1px, 0px) 0;
|
||||
--panel-color: MenuText;
|
||||
--panel-background: Menu;
|
||||
--panel-border-radius: 0;
|
||||
--panel-border-radius: env(-moz-gtk-menu-radius);
|
||||
--panel-border-color: ThreeDShadow;
|
||||
--panel-width: initial;
|
||||
}
|
||||
|
@ -334,6 +334,9 @@ class LookAndFeel {
|
||||
/** GTK titlebar radius */
|
||||
TitlebarRadius,
|
||||
|
||||
/** GTK menu radius */
|
||||
GtkMenuRadius,
|
||||
|
||||
/*
|
||||
* Not an ID; used to define the range of valid IDs. Must be last.
|
||||
*/
|
||||
|
@ -20,6 +20,13 @@ static_assert(GTK_STATE_FLAG_DIR_LTR == STATE_FLAG_DIR_LTR &&
|
||||
GTK_STATE_FLAG_DIR_RTL == STATE_FLAG_DIR_RTL,
|
||||
"incorrect direction state flags");
|
||||
|
||||
enum class CSDStyle {
|
||||
Unknown,
|
||||
Solid,
|
||||
Normal,
|
||||
};
|
||||
|
||||
static CSDStyle gCSDStyle = CSDStyle::Unknown;
|
||||
static GtkWidget* sWidgetStorage[MOZ_GTK_WIDGET_NODE_COUNT];
|
||||
static GtkStyleContext* sStyleStorage[MOZ_GTK_WIDGET_NODE_COUNT];
|
||||
|
||||
@ -70,6 +77,8 @@ static GtkWidget* CreateMenuBarWidget() {
|
||||
|
||||
static GtkWidget* CreateMenuPopupWidget() {
|
||||
GtkWidget* widget = gtk_menu_new();
|
||||
GtkStyleContext* style = gtk_widget_get_style_context(widget);
|
||||
gtk_style_context_add_class(style, GTK_STYLE_CLASS_POPUP);
|
||||
gtk_menu_attach_to_widget(GTK_MENU(widget), GetWidget(MOZ_GTK_WINDOW),
|
||||
nullptr);
|
||||
return widget;
|
||||
@ -431,8 +440,7 @@ static GtkWidget* CreateNotebookWidget() {
|
||||
return widget;
|
||||
}
|
||||
|
||||
static void CreateHeaderBarWidget(WidgetNodeType aAppearance,
|
||||
bool aIsSolidCSDStyleUsed) {
|
||||
static void CreateHeaderBarWidget(WidgetNodeType aAppearance) {
|
||||
sWidgetStorage[aAppearance] = gtk_header_bar_new();
|
||||
|
||||
GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
@ -452,7 +460,7 @@ static void CreateHeaderBarWidget(WidgetNodeType aAppearance,
|
||||
// Headerbar has to be placed to window with csd or solid-csd style
|
||||
// to properly draw the decorated.
|
||||
gtk_style_context_add_class(style,
|
||||
aIsSolidCSDStyleUsed ? "solid-csd" : "csd");
|
||||
IsSolidCSDStyleUsed() ? "solid-csd" : "csd");
|
||||
|
||||
GtkWidget* fixed = gtk_fixed_new();
|
||||
gtk_container_add(GTK_CONTAINER(window), fixed);
|
||||
@ -597,6 +605,22 @@ static bool IsToolbarButtonEnabled(ButtonLayout* aButtonLayout,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsSolidCSDStyleUsed() {
|
||||
if (gCSDStyle == CSDStyle::Unknown) {
|
||||
bool solid;
|
||||
{
|
||||
GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_titlebar(GTK_WINDOW(window), gtk_header_bar_new());
|
||||
gtk_widget_realize(window);
|
||||
GtkStyleContext* windowStyle = gtk_widget_get_style_context(window);
|
||||
solid = gtk_style_context_has_class(windowStyle, "solid-csd");
|
||||
gtk_widget_destroy(window);
|
||||
}
|
||||
gCSDStyle = solid ? CSDStyle::Solid : CSDStyle::Normal;
|
||||
}
|
||||
return gCSDStyle == CSDStyle::Solid;
|
||||
}
|
||||
|
||||
static void CreateHeaderBarButtons() {
|
||||
GtkWidget* headerBar = sWidgetStorage[MOZ_GTK_HEADER_BAR];
|
||||
MOZ_ASSERT(headerBar != nullptr, "We're missing header bar widget!");
|
||||
@ -634,18 +658,8 @@ static void CreateHeaderBarButtons() {
|
||||
}
|
||||
|
||||
static void CreateHeaderBar() {
|
||||
const bool isSolidCSDStyleUsed = []() {
|
||||
GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_titlebar(GTK_WINDOW(window), gtk_header_bar_new());
|
||||
gtk_widget_realize(window);
|
||||
GtkStyleContext* windowStyle = gtk_widget_get_style_context(window);
|
||||
bool ret = gtk_style_context_has_class(windowStyle, "solid-csd");
|
||||
gtk_widget_destroy(window);
|
||||
return ret;
|
||||
}();
|
||||
|
||||
CreateHeaderBarWidget(MOZ_GTK_HEADER_BAR, isSolidCSDStyleUsed);
|
||||
CreateHeaderBarWidget(MOZ_GTK_HEADER_BAR_MAXIMIZED, isSolidCSDStyleUsed);
|
||||
CreateHeaderBarWidget(MOZ_GTK_HEADER_BAR);
|
||||
CreateHeaderBarWidget(MOZ_GTK_HEADER_BAR_MAXIMIZED);
|
||||
CreateHeaderBarButtons();
|
||||
}
|
||||
|
||||
@ -1152,6 +1166,13 @@ static GtkStyleContext* GetCssNodeStyleInternal(WidgetNodeType aNodeType) {
|
||||
false, "MOZ_GTK_HEADER_BAR_BUTTON_RESTORE is used as an icon only!");
|
||||
return nullptr;
|
||||
}
|
||||
case MOZ_GTK_MENUPOPUP_DECORATION: {
|
||||
GtkStyleContext* parentStyle =
|
||||
CreateSubStyleWithClass(MOZ_GTK_MENUPOPUP, "csd");
|
||||
style = CreateCSSNode("decoration", parentStyle);
|
||||
g_object_unref(parentStyle);
|
||||
break;
|
||||
}
|
||||
case MOZ_GTK_WINDOW_DECORATION: {
|
||||
GtkStyleContext* parentStyle =
|
||||
CreateSubStyleWithClass(MOZ_GTK_WINDOW, "csd");
|
||||
@ -1309,12 +1330,14 @@ static GtkStyleContext* GetWidgetStyleInternal(WidgetNodeType aNodeType) {
|
||||
return style;
|
||||
}
|
||||
|
||||
void ResetWidgetCache(void) {
|
||||
void ResetWidgetCache() {
|
||||
for (int i = 0; i < MOZ_GTK_WIDGET_NODE_COUNT; i++) {
|
||||
if (sStyleStorage[i]) g_object_unref(sStyleStorage[i]);
|
||||
}
|
||||
mozilla::PodArrayZero(sStyleStorage);
|
||||
|
||||
gCSDStyle = CSDStyle::Unknown;
|
||||
|
||||
/* This will destroy all of our widgets */
|
||||
if (sWidgetStorage[MOZ_GTK_WINDOW]) {
|
||||
gtk_widget_destroy(sWidgetStorage[MOZ_GTK_WINDOW]);
|
||||
|
@ -50,7 +50,7 @@ GtkStyleContext* CreateStyleContextWithStates(
|
||||
GtkTextDirection aDirection = GTK_TEXT_DIR_NONE,
|
||||
GtkStateFlags aStateFlags = GTK_STATE_FLAG_NORMAL);
|
||||
|
||||
void ResetWidgetCache(void);
|
||||
void ResetWidgetCache();
|
||||
|
||||
bool IsSolidCSDStyleUsed();
|
||||
|
||||
|
@ -347,6 +347,8 @@ enum WidgetNodeType : int {
|
||||
MOZ_GTK_WINDOW_DECORATION,
|
||||
MOZ_GTK_WINDOW_DECORATION_SOLID,
|
||||
|
||||
MOZ_GTK_MENUPOPUP_DECORATION,
|
||||
|
||||
MOZ_GTK_WIDGET_NODE_COUNT
|
||||
};
|
||||
|
||||
|
@ -122,6 +122,20 @@ nsLookAndFeel::~nsLookAndFeel() {
|
||||
gtk_settings_get_default(), FuncToGpointer(settings_changed_cb), nullptr);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void DumpStyleContext(GtkStyleContext* aStyle) {
|
||||
static auto sGtkStyleContextToString =
|
||||
reinterpret_cast<char* (*)(GtkStyleContext*, gint)>(
|
||||
dlsym(RTLD_DEFAULT, "gtk_style_context_to_string"));
|
||||
char* str = sGtkStyleContextToString(aStyle, ~0);
|
||||
printf("%s\n", str);
|
||||
g_free(str);
|
||||
str = gtk_widget_path_to_string(gtk_style_context_get_path(aStyle));
|
||||
printf("%s\n", str);
|
||||
g_free(str);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Modifies color |*aDest| as if a pattern of color |aSource| was painted with
|
||||
// CAIRO_OPERATOR_OVER to a surface with color |*aDest|.
|
||||
static void ApplyColorOver(const GdkRGBA& aSource, GdkRGBA* aDest) {
|
||||
@ -837,6 +851,11 @@ nsresult nsLookAndFeel::NativeGetInt(IntID aID, int32_t& aResult) {
|
||||
aResult = EffectiveTheme().mTitlebarRadius;
|
||||
break;
|
||||
}
|
||||
case IntID::GtkMenuRadius: {
|
||||
EnsureInit();
|
||||
aResult = EffectiveTheme().mMenuRadius;
|
||||
break;
|
||||
}
|
||||
case IntID::AllowOverlayScrollbarsOverlap: {
|
||||
aResult = 1;
|
||||
break;
|
||||
@ -1406,6 +1425,35 @@ static nscolor GetBackgroundColor(
|
||||
return NS_TRANSPARENT;
|
||||
}
|
||||
|
||||
static int32_t GetBorderRadius(GtkStyleContext* aStyle) {
|
||||
GValue value = G_VALUE_INIT;
|
||||
// NOTE(emilio): In an ideal world, we'd query the two longhands
|
||||
// (border-top-left-radius and border-top-right-radius) separately. However,
|
||||
// that doesn't work (GTK rejects the query with:
|
||||
//
|
||||
// Style property "border-top-left-radius" is not gettable
|
||||
//
|
||||
// However! Getting border-radius does work, and it does return the
|
||||
// border-top-left-radius as a gint:
|
||||
//
|
||||
// https://docs.gtk.org/gtk3/const.STYLE_PROPERTY_BORDER_RADIUS.html
|
||||
// https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-20/gtk/gtkcssshorthandpropertyimpl.c#L961-977
|
||||
//
|
||||
// So we abuse this fact, and make the assumption here that the
|
||||
// border-top-{left,right}-radius are the same, and roll with it.
|
||||
gtk_style_context_get_property(aStyle, "border-radius", GTK_STATE_FLAG_NORMAL,
|
||||
&value);
|
||||
auto unset = MakeScopeExit([&] { g_value_unset(&value); });
|
||||
|
||||
auto type = G_VALUE_TYPE(&value);
|
||||
if (type == G_TYPE_INT) {
|
||||
return g_value_get_int(&value);
|
||||
}
|
||||
NS_WARNING(nsPrintfCString("Unknown value type %lu for titlebar radius", type)
|
||||
.get());
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nsLookAndFeel::PerThemeData::Init() {
|
||||
mName = GetGtkTheme();
|
||||
|
||||
@ -1533,36 +1581,7 @@ void nsLookAndFeel::PerThemeData::Init() {
|
||||
mTitlebarInactiveText = GDK_RGBA_TO_NS_RGBA(color);
|
||||
mTitlebarInactiveBackground =
|
||||
GetBackgroundColor(style, mTitlebarText, GTK_STATE_FLAG_BACKDROP);
|
||||
|
||||
GValue value = G_VALUE_INIT;
|
||||
// NOTE(emilio): In an ideal world, we'd query the two longhands
|
||||
// (border-top-left-radius and border-top-right-radius) separately. However,
|
||||
// that doesn't work (GTK rejects the query with:
|
||||
//
|
||||
// Style property "border-top-left-radius" is not gettable
|
||||
//
|
||||
// However! Getting border-radius does work, and it does return the
|
||||
// border-top-left-radius as a gint:
|
||||
//
|
||||
// https://docs.gtk.org/gtk3/const.STYLE_PROPERTY_BORDER_RADIUS.html
|
||||
// https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-20/gtk/gtkcssshorthandpropertyimpl.c#L961-977
|
||||
//
|
||||
// So we abuse this fact, and make the assumption here that the
|
||||
// border-top-{left,right}-radius are the same, and roll with it.
|
||||
gtk_style_context_get_property(style, "border-radius",
|
||||
GTK_STATE_FLAG_NORMAL, &value);
|
||||
|
||||
mTitlebarRadius = [&]() -> int {
|
||||
auto type = G_VALUE_TYPE(&value);
|
||||
if (type == G_TYPE_INT) {
|
||||
return g_value_get_int(&value);
|
||||
}
|
||||
NS_WARNING(
|
||||
nsPrintfCString("Unknown value type %lu for titlebar radius", type)
|
||||
.get());
|
||||
return 0;
|
||||
}();
|
||||
g_value_unset(&value);
|
||||
mTitlebarRadius = IsSolidCSDStyleUsed() ? 0 : GetBorderRadius(style);
|
||||
}
|
||||
|
||||
style = GetStyleContext(MOZ_GTK_MENUPOPUP);
|
||||
@ -1585,6 +1604,14 @@ void nsLookAndFeel::PerThemeData::Init() {
|
||||
"background");
|
||||
return mMozWindowBackground;
|
||||
}();
|
||||
mMenuRadius = 0;
|
||||
if (!IsSolidCSDStyleUsed()) {
|
||||
mMenuRadius = GetBorderRadius(style);
|
||||
if (!mMenuRadius) {
|
||||
mMenuRadius =
|
||||
GetBorderRadius(GetStyleContext(MOZ_GTK_MENUPOPUP_DECORATION));
|
||||
}
|
||||
}
|
||||
|
||||
style = GetStyleContext(MOZ_GTK_MENUITEM);
|
||||
gtk_style_context_get_color(style, GTK_STATE_FLAG_PRELIGHT, &color);
|
||||
@ -1825,6 +1852,7 @@ void nsLookAndFeel::PerThemeData::Init() {
|
||||
NS_SUCCEEDED(rv) ? color : 0);
|
||||
}
|
||||
LOGLNF(" * titlebar-radius: %d\n", mTitlebarRadius);
|
||||
LOGLNF(" * menu-radius: %d\n", mMenuRadius);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,6 +124,7 @@ class nsLookAndFeel final : public nsXPLookAndFeel {
|
||||
|
||||
float mCaretRatio = 0.0f;
|
||||
int32_t mTitlebarRadius = 0;
|
||||
int32_t mMenuRadius = 0;
|
||||
char16_t mInvisibleCharacter = 0;
|
||||
bool mMenuSupportsDrag = false;
|
||||
|
||||
|
@ -175,6 +175,7 @@ static const char sIntPrefs[][43] = {
|
||||
"ui.systemHorizontalScrollbarHeight",
|
||||
"ui.touchDeviceSupportPresent",
|
||||
"ui.titlebarRadius",
|
||||
"ui.GtkMenuRadius",
|
||||
};
|
||||
|
||||
static_assert(ArrayLength(sIntPrefs) == size_t(LookAndFeel::IntID::End),
|
||||
|
@ -2231,6 +2231,7 @@ STATIC_ATOMS = [
|
||||
Atom("_moz_gtk_csd_maximize_button", "-moz-gtk-csd-maximize-button"),
|
||||
Atom("_moz_gtk_csd_close_button", "-moz-gtk-csd-close-button"),
|
||||
Atom("_moz_gtk_csd_reversed_placement", "-moz-gtk-csd-reversed-placement"),
|
||||
Atom("_moz_gtk_menu_radius", "-moz-gtk-menu-radius"),
|
||||
Atom("_moz_proton", "-moz-proton"),
|
||||
Atom("_moz_proton_places_tooltip", "-moz-proton-places-tooltip"),
|
||||
Atom("_moz_system_dark_theme", "-moz-system-dark-theme"),
|
||||
|
Loading…
Reference in New Issue
Block a user