Bug 1432090 - Honor GTK button layout. r=stransky,desktop-theme-reviewers,dao

This is based off work by smurfd. But this patch doesn't support buttons
both at the left and right, which simplifies a lot the implementation.

Also, clean-up the existing env variables while at it.

Co-authored-by: Nicklas Boman <smurfd@gmail.com>

Differential Revision: https://phabricator.services.mozilla.com/D132073
This commit is contained in:
Emilio Cobos Álvarez 2021-11-26 11:37:52 +00:00
parent 6a0cba6df9
commit 4354146592
10 changed files with 90 additions and 59 deletions

View File

@ -397,18 +397,22 @@ menuitem.bookmark-item {
.titlebar-min {
appearance: auto;
-moz-default-appearance: -moz-window-button-minimize;
-moz-box-ordinal-group: env(-moz-gtk-csd-minimize-button-position);
}
.titlebar-max {
appearance: auto;
-moz-default-appearance: -moz-window-button-maximize;
-moz-box-ordinal-group: env(-moz-gtk-csd-maximize-button-position);
}
.titlebar-restore {
appearance: auto;
-moz-default-appearance: -moz-window-button-restore;
-moz-box-ordinal-group: env(-moz-gtk-csd-maximize-button-position);
}
.titlebar-close {
appearance: auto;
-moz-default-appearance: -moz-window-button-close;
-moz-box-ordinal-group: env(-moz-gtk-csd-close-button-position);
}
/* When using lightweight themes, use our own buttons since native ones might
@ -466,8 +470,7 @@ menuitem.bookmark-item {
}
@media (-moz-gtk-csd-reversed-placement) {
.titlebar-buttonbox-container,
.titlebar-close {
.titlebar-buttonbox-container {
-moz-box-ordinal-group: 0;
}
}

View File

@ -5,6 +5,10 @@
<script>
const NON_CONTENT_ACCESSIBLE_ENV_VARS = [
"-moz-gtk-csd-titlebar-radius",
"-moz-gtk-csd-menu-radius",
"-moz-gtk-csd-minimize-button-position",
"-moz-gtk-csd-maximize-button-position",
"-moz-gtk-csd-close-button-position",
];
const div = document.querySelector("div");

View File

@ -49,19 +49,19 @@ macro_rules! make_variable {
}
fn get_safearea_inset_top(device: &Device) -> VariableValue {
VariableValue::pixel(device.safe_area_insets().top)
VariableValue::pixels(device.safe_area_insets().top)
}
fn get_safearea_inset_bottom(device: &Device) -> VariableValue {
VariableValue::pixel(device.safe_area_insets().bottom)
VariableValue::pixels(device.safe_area_insets().bottom)
}
fn get_safearea_inset_left(device: &Device) -> VariableValue {
VariableValue::pixel(device.safe_area_insets().left)
VariableValue::pixels(device.safe_area_insets().left)
}
fn get_safearea_inset_right(device: &Device) -> VariableValue {
VariableValue::pixel(device.safe_area_insets().right)
VariableValue::pixels(device.safe_area_insets().right)
}
static ENVIRONMENT_VARIABLES: [EnvironmentVariable; 4] = [
@ -71,17 +71,47 @@ static ENVIRONMENT_VARIABLES: [EnvironmentVariable; 4] = [
make_variable!(atom!("safe-area-inset-right"), get_safearea_inset_right),
];
fn get_titlebar_radius(device: &Device) -> VariableValue {
VariableValue::pixel(device.titlebar_radius())
macro_rules! lnf_int {
($id:ident) => {
unsafe {
crate::gecko_bindings::bindings::Gecko_GetLookAndFeelInt(
crate::gecko_bindings::bindings::LookAndFeel_IntID::$id as i32,
)
}
};
}
fn get_menu_radius(device: &Device) -> VariableValue {
VariableValue::pixel(device.menu_radius())
macro_rules! lnf_int_variable {
($atom:expr, $id:ident, $ctor:ident) => {{
fn __eval(_: &Device) -> VariableValue {
VariableValue::$ctor(lnf_int!($id))
}
make_variable!($atom, __eval)
}};
}
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),
static CHROME_ENVIRONMENT_VARIABLES: [EnvironmentVariable; 5] = [
lnf_int_variable!(
atom!("-moz-gtk-csd-titlebar-radius"),
TitlebarRadius,
int_pixels
),
lnf_int_variable!(atom!("-moz-gtk-csd-menu-radius"), GtkMenuRadius, int_pixels),
lnf_int_variable!(
atom!("-moz-gtk-csd-close-button-position"),
GTKCSDCloseButtonPosition,
integer
),
lnf_int_variable!(
atom!("-moz-gtk-csd-minimize-button-position"),
GTKCSDMinimizeButtonPosition,
integer
),
lnf_int_variable!(
atom!("-moz-gtk-csd-maximize-button-position"),
GTKCSDMaximizeButtonPosition,
integer
),
];
impl CssEnvironment {
@ -280,17 +310,39 @@ impl VariableValue {
}))
}
/// Create VariableValue from css pixel value
pub fn pixel(number: f32) -> Self {
/// Create VariableValue from an int.
fn integer(number: i32) -> Self {
Self::from_token(Token::Number {
has_sign: false,
value: number as f32,
int_value: Some(number),
})
}
/// Create VariableValue from a float amount of CSS pixels.
fn pixels(number: f32) -> Self {
// FIXME (https://github.com/servo/rust-cssparser/issues/266):
// No way to get TokenSerializationType::Dimension without creating
// Token object.
let token = Token::Dimension {
Self::from_token(Token::Dimension {
has_sign: false,
value: number,
int_value: None,
unit: CowRcStr::from("px"),
};
})
}
/// Create VariableValue from an integer amount of CSS pixels.
fn int_pixels(number: i32) -> Self {
Self::from_token(Token::Dimension {
has_sign: false,
value: number as f32,
int_value: Some(number),
unit: CowRcStr::from("px"),
})
}
fn from_token(token: Token) -> Self {
let token_type = token.serialization_type();
let mut css = token.to_css_string();
css.shrink_to_fit();

View File

@ -387,22 +387,6 @@ impl Device {
}
}
/// Returns the gtk titlebar radius in CSS pixels.
pub fn titlebar_radius(&self) -> f32 {
unsafe {
bindings::Gecko_GetLookAndFeelInt(bindings::LookAndFeel_IntID::TitlebarRadius as i32)
as f32
}
}
/// 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 {

View File

@ -10,10 +10,10 @@
menupopup,
panel {
min-width: 1px;
--panel-padding: max(env(-moz-gtk-menu-radius) - 1px, 0px) 0;
--panel-padding: max(env(-moz-gtk-csd-menu-radius) - 1px, 0px) 0;
--panel-color: MenuText;
--panel-background: Menu;
--panel-border-radius: env(-moz-gtk-menu-radius);
--panel-border-radius: env(-moz-gtk-csd-menu-radius);
--panel-border-color: ThreeDShadow;
--panel-width: initial;
/* To account for the box-shadow below */

View File

@ -264,25 +264,19 @@ class LookAndFeel {
/**
* An Integer value that will represent the position of the Minimize button
* in GTK Client side decoration header. Its value will be between 0 and 2
* if it is on the left side of the tabbar, otherwise it will be between
* 3 and 5.
* in GTK Client side decoration header.
*/
GTKCSDMinimizeButtonPosition,
/**
* An Integer value that will represent the position of the Maximize button
* in GTK Client side decoration header. Its value will be between 0 and 2
* if it is on the left side of the tabbar, otherwise it will be between
* 3 and 5.
* in GTK Client side decoration header.
*/
GTKCSDMaximizeButtonPosition,
/**
* An Integer value that will represent the position of the Close button
* in GTK Client side decoration header. Its value will be between 0 and 2
* if it is on the left side of the tabbar, otherwise it will be between
* 3 and 5.
* in GTK Client side decoration header.
*/
GTKCSDCloseButtonPosition,

View File

@ -426,30 +426,25 @@ size_t GetGtkHeaderBarButtonLayout(Span<ButtonLayout> aButtonLayout,
nsDependentCSubstring layout(decorationLayout, strlen(decorationLayout));
bool right = false;
size_t activeButtons = 0;
for (const auto& part : layout.Split(':')) {
for (const auto& button : part.Split(',')) {
if (button.EqualsLiteral("close")) {
aButtonLayout[activeButtons++] = {MOZ_GTK_HEADER_BAR_BUTTON_CLOSE,
right};
aButtonLayout[activeButtons++] = {MOZ_GTK_HEADER_BAR_BUTTON_CLOSE};
} else if (button.EqualsLiteral("minimize")) {
aButtonLayout[activeButtons++] = {MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE,
right};
aButtonLayout[activeButtons++] = {MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE};
} else if (button.EqualsLiteral("maximize")) {
aButtonLayout[activeButtons++] = {MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE,
right};
aButtonLayout[activeButtons++] = {MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE};
}
if (activeButtons == aButtonLayout.Length()) {
return activeButtons;
}
}
right = true;
}
return activeButtons;
}
static void EnsureToolbarMetrics(void) {
static void EnsureToolbarMetrics() {
if (!sToolbarMetrics.initialized) {
// Make sure we have clean cache after theme reset, etc.
memset(&sToolbarMetrics, 0, sizeof(sToolbarMetrics));
@ -457,7 +452,7 @@ static void EnsureToolbarMetrics(void) {
// Calculate titlebar button visibility and positions.
ButtonLayout aButtonLayout[TOOLBAR_BUTTONS];
size_t activeButtonNums =
GetGtkHeaderBarButtonLayout(mozilla::Span(aButtonLayout), nullptr);
GetGtkHeaderBarButtonLayout(Span(aButtonLayout), nullptr);
for (size_t i = 0; i < activeButtonNums; i++) {
int buttonIndex =

View File

@ -356,7 +356,6 @@ enum WidgetNodeType : int {
* right side of the tab bar */
struct ButtonLayout {
WidgetNodeType mType;
bool mAtRight;
};
/*** General library functions ***/

View File

@ -1293,9 +1293,6 @@ void nsLookAndFeel::EnsureInit() {
if (pos) {
*pos = i;
if (layout.mAtRight) {
*pos += TOOLBAR_BUTTONS;
}
}
}

View File

@ -2229,10 +2229,13 @@ STATIC_ATOMS = [
Atom("_moz_gtk_csd_available", "-moz-gtk-csd-available"),
Atom("_moz_gtk_csd_titlebar_radius", "-moz-gtk-csd-titlebar-radius"),
Atom("_moz_gtk_csd_minimize_button", "-moz-gtk-csd-minimize-button"),
Atom("_moz_gtk_csd_minimize_button_position", "-moz-gtk-csd-minimize-button-position"),
Atom("_moz_gtk_csd_maximize_button", "-moz-gtk-csd-maximize-button"),
Atom("_moz_gtk_csd_maximize_button_position", "-moz-gtk-csd-maximize-button-position"),
Atom("_moz_gtk_csd_close_button", "-moz-gtk-csd-close-button"),
Atom("_moz_gtk_csd_close_button_position", "-moz-gtk-csd-close-button-position"),
Atom("_moz_gtk_csd_reversed_placement", "-moz-gtk-csd-reversed-placement"),
Atom("_moz_gtk_menu_radius", "-moz-gtk-menu-radius"),
Atom("_moz_gtk_csd_menu_radius", "-moz-gtk-csd-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"),