Bug 1433667 - Honour system titlebar button left/right placement, r=dao

Differential Revision: https://phabricator.services.mozilla.com/D16466

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Martin Stransky 2019-01-18 13:52:29 +00:00
parent 1128d243c6
commit 8ddc948f81
15 changed files with 92 additions and 19 deletions

View File

@ -285,14 +285,28 @@ window:not([chromehidden~="toolbar"]) #nav-bar[nonemptyoverflow] > .overflow-but
#toolbar-menubar:not([autohide=true]) + #TabsToolbar .titlebar-spacer,
%endif
%ifndef MOZ_WIDGET_COCOA
%ifndef MOZ_WIDGET_GTK
:root:not([sizemode=normal]) .titlebar-spacer[type="pre-tabs"],
%endif
%endif
:root:not([chromemargin]) .titlebar-buttonbox-container,
:root[inFullscreen] .titlebar-buttonbox-container,
:root[inFullscreen] .titlebar-spacer,
:root:not([tabsintitlebar]) .titlebar-spacer {
display: none;
}
%ifdef MOZ_WIDGET_GTK
@media (-moz-gtk-csd-reversed-placement: 0) {
:root:not([sizemode=normal]) .titlebar-spacer[type="pre-tabs"] {
display: none;
}
}
@media (-moz-gtk-csd-reversed-placement) {
:root:not([sizemode=normal]) .titlebar-spacer[type="post-tabs"] {
display: none;
}
}
%endif
%ifdef MENUBAR_CAN_AUTOHIDE
#toolbar-menubar[autohide=true]:not([inactive]) + #TabsToolbar > .titlebar-buttonbox-container {

View File

@ -716,4 +716,10 @@ notification[value="translation"] menulist > .menulist-dropmarker {
display: none;
}
}
@media (-moz-gtk-csd-reversed-placement) {
.titlebar-buttonbox-container,
.titlebar-close {
-moz-box-ordinal-group: 0;
}
}
}

View File

@ -425,6 +425,13 @@ PointerCapabilities Gecko_MediaFeatures_AllPointerCapabilities(
(nsStaticAtom*)nsGkAtoms::_moz_gtk_csd_close_button);
}
rv = LookAndFeel::GetInt(LookAndFeel::eIntID_GTKCSDReversedPlacement,
&metricResult);
if (NS_SUCCEEDED(rv) && metricResult) {
sSystemMetrics->AppendElement(
(nsStaticAtom*)nsGkAtoms::_moz_gtk_csd_reversed_placement);
}
metricResult = LookAndFeel::GetInt(LookAndFeel::eIntID_SystemUsesDarkTheme);
if (metricResult) {
sSystemMetrics->AppendElement(

View File

@ -59,6 +59,7 @@ var suppressed_toggles = [
"-moz-gtk-csd-minimize-button",
"-moz-gtk-csd-maximize-button",
"-moz-gtk-csd-close-button",
"-moz-gtk-csd-reversed-placement",
];
var toggles_enabled_in_content = [

View File

@ -699,6 +699,7 @@ function run() {
expression_should_not_be_parseable("-moz-gtk-csd-minimize-button");
expression_should_not_be_parseable("-moz-gtk-csd-maximize-button");
expression_should_not_be_parseable("-moz-gtk-csd-close-button");
expression_should_not_be_parseable("-moz-gtk-csd-reversed-placement");
expression_should_be_parseable("-moz-touch-enabled");
expression_should_not_be_parseable("-moz-scrollbar-start-backward: 0");
@ -721,6 +722,7 @@ function run() {
expression_should_not_be_parseable("-moz-gtk-csd-minimize-button: 0");
expression_should_not_be_parseable("-moz-gtk-csd-maximize-button: 0");
expression_should_not_be_parseable("-moz-gtk-csd-close-button: 0");
expression_should_not_be_parseable("-moz-gtk-csd-reversed-placement: 0");
expression_should_be_parseable("-moz-touch-enabled: 0");
expression_should_not_be_parseable("-moz-scrollbar-start-backward: 1");
@ -743,6 +745,7 @@ function run() {
expression_should_not_be_parseable("-moz-gtk-csd-minimize-button: 1");
expression_should_not_be_parseable("-moz-gtk-csd-maximize-button: 1");
expression_should_not_be_parseable("-moz-gtk-csd-close-button: 1");
expression_should_not_be_parseable("-moz-gtk-csd-reversed-placement: 1");
expression_should_be_parseable("-moz-touch-enabled: 1");
expression_should_not_be_parseable("-moz-scrollbar-start-backward: -1");
@ -766,6 +769,7 @@ function run() {
expression_should_not_be_parseable("-moz-gtk-csd-minimize-button: -1");
expression_should_not_be_parseable("-moz-gtk-csd-maximize-button: -1");
expression_should_not_be_parseable("-moz-gtk-csd-close-button: -1");
expression_should_not_be_parseable("-moz-gtk-csd-reversed-placement: -1");
expression_should_not_be_parseable("-moz-scrollbar-start-backward: true");
expression_should_not_be_parseable("-moz-scrollbar-start-forward: true");
@ -788,6 +792,7 @@ function run() {
expression_should_not_be_parseable("-moz-gtk-csd-minimize-button: true");
expression_should_not_be_parseable("-moz-gtk-csd-maximize-button: true");
expression_should_not_be_parseable("-moz-gtk-csd-close-button: true");
expression_should_not_be_parseable("-moz-gtk-csd-reversed-placement: true");
// os version media queries (currently windows only)
expression_should_not_be_parseable("-moz-os-version: windows-win7");

View File

@ -526,7 +526,7 @@ lazy_static! {
/// to support new types in these entries and (2) ensuring that either
/// nsPresContext::MediaFeatureValuesChanged is called when the value that
/// would be returned by the evaluator function could change.
pub static ref MEDIA_FEATURES: [MediaFeatureDescription; 51] = [
pub static ref MEDIA_FEATURES: [MediaFeatureDescription; 52] = [
feature!(
atom!("width"),
AllowsRanges::Yes,
@ -724,6 +724,7 @@ lazy_static! {
system_metric_feature!(atom!("-moz-gtk-csd-minimize-button")),
system_metric_feature!(atom!("-moz-gtk-csd-maximize-button")),
system_metric_feature!(atom!("-moz-gtk-csd-close-button")),
system_metric_feature!(atom!("-moz-gtk-csd-reversed-placement")),
system_metric_feature!(atom!("-moz-system-dark-theme")),
// This is the only system-metric media feature that's accessible to
// content as of today.

View File

@ -448,6 +448,12 @@ class LookAndFeel {
*/
eIntID_GTKCSDCloseButton,
/*
* A boolean value indicating whether titlebar buttons are located
* in left titlebar corner.
*/
eIntID_GTKCSDReversedPlacement,
/*
* A boolean value indicating whether or not the OS is using a dark theme,
* which we may want to switch to as well if not overridden by the user.

View File

@ -633,8 +633,9 @@ static void CreateHeaderBarButtons() {
GTK_STYLE_CLASS_LEFT);
WidgetNodeType buttonLayout[TOOLBAR_BUTTONS];
int activeButtons =
GetGtkHeaderBarButtonLayout(buttonLayout, TOOLBAR_BUTTONS);
GetGtkHeaderBarButtonLayout(buttonLayout, TOOLBAR_BUTTONS, nullptr);
if (IsToolbarButtonEnabled(buttonLayout, activeButtons,
MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE)) {

View File

@ -391,9 +391,15 @@ static void CalculateToolbarButtonSpacing(WidgetNodeType aAppearance,
}
int GetGtkHeaderBarButtonLayout(WidgetNodeType* aButtonLayout,
int aMaxButtonNums) {
NS_ASSERTION(aMaxButtonNums >= TOOLBAR_BUTTONS,
"Requested number of buttons is higher than storage capacity!");
int aMaxButtonNums,
bool* aReversedButtonsPlacement) {
#if DEBUG
if (aButtonLayout) {
NS_ASSERTION(
aMaxButtonNums >= TOOLBAR_BUTTONS,
"Requested number of buttons is higher than storage capacity!");
}
#endif
const gchar* decorationLayout = nullptr;
GtkSettings* settings = gtk_settings_get_for_screen(gdk_screen_get_default());
@ -401,20 +407,28 @@ int GetGtkHeaderBarButtonLayout(WidgetNodeType* aButtonLayout,
// Use a default layout
if (!decorationLayout) {
decorationLayout = "minimize,maximize,close";
decorationLayout = "menu:minimize,maximize,close";
}
// We support only default button order now:
// minimize/maximize/close
int activeButtonNums = 0;
if (strstr(decorationLayout, "minimize") != nullptr) {
aButtonLayout[activeButtonNums++] = MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE;
if (aButtonLayout) {
if (strstr(decorationLayout, "minimize") != nullptr) {
aButtonLayout[activeButtonNums++] = MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE;
}
if (strstr(decorationLayout, "maximize") != nullptr) {
aButtonLayout[activeButtonNums++] = MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE;
}
if (strstr(decorationLayout, "close") != nullptr) {
aButtonLayout[activeButtonNums++] = MOZ_GTK_HEADER_BAR_BUTTON_CLOSE;
}
}
if (strstr(decorationLayout, "maximize") != nullptr) {
aButtonLayout[activeButtonNums++] = MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE;
}
if (strstr(decorationLayout, "close") != nullptr) {
aButtonLayout[activeButtonNums++] = MOZ_GTK_HEADER_BAR_BUTTON_CLOSE;
// "minimize,maximize,close:menu" layout means buttons are on the opposite
// titlebar side.
if (aReversedButtonsPlacement) {
*aReversedButtonsPlacement = strstr(decorationLayout, ":menu") != nullptr;
}
return activeButtonNums;
@ -435,7 +449,7 @@ static void EnsureToolbarMetrics(void) {
// Calculate titlebar button visibility and positions.
WidgetNodeType aButtonLayout[TOOLBAR_BUTTONS];
int activeButtonNums =
GetGtkHeaderBarButtonLayout(aButtonLayout, TOOLBAR_BUTTONS);
GetGtkHeaderBarButtonLayout(aButtonLayout, TOOLBAR_BUTTONS, nullptr);
for (int i = 0; i < activeButtonNums; i++) {
int buttonIndex = (aButtonLayout[i] - MOZ_GTK_HEADER_BAR_BUTTON_CLOSE);
@ -2349,7 +2363,12 @@ gint moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top,
style = GetStyleContext(MOZ_GTK_HEADER_BAR);
moz_gtk_add_border_padding(style, left, top, right, bottom);
*top = *bottom = 0;
bool leftButtonsPlacement;
GetGtkHeaderBarButtonLayout(nullptr, 0, &leftButtonsPlacement);
if (direction == GTK_TEXT_DIR_RTL) {
leftButtonsPlacement = !leftButtonsPlacement;
}
if (leftButtonsPlacement) {
*right = 0;
} else {
*left = 0;

View File

@ -598,14 +598,17 @@ const ToolbarButtonGTKMetrics* GetToolbarButtonMetrics(
* Get toolbar button layout.
* aButtonLayout: [IN][OUT] An array which will be filled by WidgetNodeType
* references to visible titlebar buttons.
Must contains at least TOOLBAR_BUTTONS entries.
* Must contains at least TOOLBAR_BUTTONS entries.
* aMaxButtonNums: [IN] Allocated aButtonLayout entries. Must be at least
TOOLBAR_BUTTONS wide.
* TOOLBAR_BUTTONS wide.
* aReversedButtonsPlacement: [OUT] True if the buttons are placed in opposite
* titlebar corner.
*
* returns: Number of returned entries at aButtonLayout.
*/
int GetGtkHeaderBarButtonLayout(WidgetNodeType* aButtonLayout,
int aMaxButtonNums);
int aMaxButtonNums,
bool* aReversedButtonsPlacement);
/**
* Get size of CSD window extents of given GtkWindow.

View File

@ -692,6 +692,10 @@ nsresult nsLookAndFeel::GetIntImpl(IntID aID, int32_t& aResult) {
case eIntID_GTKCSDTransparentBackground:
aResult = nsWindow::TopLevelWindowUseARGBVisual();
break;
case eIntID_GTKCSDReversedPlacement:
EnsureInit();
aResult = mCSDReversedPlacement;
break;
case eIntID_PrefersReducedMotion: {
GtkSettings* settings;
gboolean enableAnimations;
@ -1121,8 +1125,8 @@ void nsLookAndFeel::EnsureInit() {
// as -moz-gtk* media features.
WidgetNodeType buttonLayout[TOOLBAR_BUTTONS];
int activeButtons =
GetGtkHeaderBarButtonLayout(buttonLayout, TOOLBAR_BUTTONS);
int activeButtons = GetGtkHeaderBarButtonLayout(buttonLayout, TOOLBAR_BUTTONS,
&mCSDReversedPlacement);
for (int i = 0; i < activeButtons; i++) {
switch (buttonLayout[i]) {
case MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE:

View File

@ -90,6 +90,7 @@ class nsLookAndFeel final : public nsXPLookAndFeel {
bool mCSDMaximizeButton;
bool mCSDMinimizeButton;
bool mCSDCloseButton;
bool mCSDReversedPlacement;
bool mInitialized;
void EnsureInit();

View File

@ -284,6 +284,9 @@ nsresult HeadlessLookAndFeel::GetIntImpl(IntID aID, int32_t& aResult) {
case eIntID_GTKCSDCloseButton:
aResult = 1;
break;
case eIntID_GTKCSDReversedPlacement:
aResult = 0;
break;
default:
NS_WARNING(
"HeadlessLookAndFeel::GetIntImpl called with an unrecognized aID");

View File

@ -78,6 +78,7 @@ nsLookAndFeelIntPref nsXPLookAndFeel::sIntPrefs[] = {
{"ui.GtkCSDMinimizeButton", eIntID_GTKCSDMinimizeButton, false, 0},
{"ui.GtkCSDMaximizeButton", eIntID_GTKCSDMaximizeButton, false, 0},
{"ui.GtkCSDCloseButton", eIntID_GTKCSDCloseButton, false, 0},
{"ui.GtkCSDReversedPlacement", eIntID_GTKCSDReversedPlacement, false, 0},
{"ui.systemUsesDarkTheme", eIntID_SystemUsesDarkTheme, false, 0},
{"ui.prefersReducedMotion", eIntID_PrefersReducedMotion, false, 0},
{"ui.primaryPointerCapabilities", eIntID_PrimaryPointerCapabilities, false,

View File

@ -2168,6 +2168,7 @@ STATIC_ATOMS = [
Atom("_moz_gtk_csd_minimize_button", "-moz-gtk-csd-minimize-button"),
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_system_dark_theme", "-moz-system-dark-theme"),
# application commands