diff --git a/layout/xul/nsMenuPopupFrame.cpp b/layout/xul/nsMenuPopupFrame.cpp index 8ebb8b01d5fe..254078c0185e 100644 --- a/layout/xul/nsMenuPopupFrame.cpp +++ b/layout/xul/nsMenuPopupFrame.cpp @@ -2186,6 +2186,12 @@ nsMargin nsMenuPopupFrame::GetMargin() const { margin.left += auOffset.x; margin.right += auOffset.x; } + if (mPopupType == PopupType::Tooltip) { + const auto auOffset = + CSSPixel::ToAppUnits(LookAndFeel::TooltipOffsetVertical()); + margin.top += auOffset; + margin.bottom += auOffset; + } return margin; } diff --git a/toolkit/content/tests/chrome/window_tooltip.xhtml b/toolkit/content/tests/chrome/window_tooltip.xhtml index b78075de453c..ba63793614c3 100644 --- a/toolkit/content/tests/chrome/window_tooltip.xhtml +++ b/toolkit/content/tests/chrome/window_tooltip.xhtml @@ -30,6 +30,8 @@ var gOriginalWidth = -1; var gOriginalHeight = -1; var gButton = null; +const kTooltipOffsetVertical = 10; + function runTest() { startPopupTests(popupTests); @@ -112,7 +114,7 @@ var popupTests = [ Math.round(buttonrect.left + parseFloat(popupstyle.marginLeft) + 6), testname + " left position of tooltip"); is(Math.round(rect.top), - Math.round(buttonrect.top + parseFloat(popupstyle.marginTop) + 6), + Math.round(buttonrect.top + parseFloat(popupstyle.marginTop) + 6 + kTooltipOffsetVertical), testname + " top position of tooltip"); var labelrect = document.getElementById("label").getBoundingClientRect(); @@ -159,7 +161,7 @@ var popupTests = [ Math.round(buttonrect.left + parseFloat(popupstyle.marginLeft) + 4), testname + " left position of tooltip"); is(Math.round(rect.top), - Math.round(buttonrect.top + parseFloat(popupstyle.marginTop) + 4), + Math.round(buttonrect.top + parseFloat(popupstyle.marginTop) + 4 + kTooltipOffsetVertical), testname + " top position of tooltip"); var labelrect = document.getElementById("label").getBoundingClientRect(); @@ -204,7 +206,7 @@ var popupTests = [ Math.round(buttonrect.left + parseFloat(popupstyle.marginLeft) + 6), testname + " left position of tooltip"); is(Math.round(rect.top), - Math.round(buttonrect.top + parseFloat(popupstyle.marginTop) + 6), + Math.round(buttonrect.top + parseFloat(popupstyle.marginTop) + 6 + kTooltipOffsetVertical), testname + " top position of tooltip"); var labelrect = document.getElementById("label").getBoundingClientRect(); @@ -359,7 +361,14 @@ function moveWindowTo(x, y, callback, arg) } } -window.arguments[0].SimpleTest.waitForFocus(runTest, window); +(async function() { + let parent = window.arguments[0]; + await Promise.all([ + parent.SimpleTest.promiseFocus(window), + parent.SpecialPowers.pushPrefEnv({set: [["ui.tooltipOffsetVertical", kTooltipOffsetVertical]]}), + ]); + runTest(); +})(); ]]> diff --git a/toolkit/content/xul.css b/toolkit/content/xul.css index ead99972950a..908132d59808 100644 --- a/toolkit/content/xul.css +++ b/toolkit/content/xul.css @@ -389,10 +389,6 @@ tooltip { pointer-events: none; } -tooltip:not([position]) { - margin-top: 21px; -} - /** * It's important that these styles are in a UA sheet, because the default * tooltip is native anonymous content diff --git a/widget/LookAndFeel.h b/widget/LookAndFeel.h index 0cab187410e3..c9581f90af22 100644 --- a/widget/LookAndFeel.h +++ b/widget/LookAndFeel.h @@ -186,6 +186,7 @@ class LookAndFeel { */ ContextMenuOffsetVertical, ContextMenuOffsetHorizontal, + TooltipOffsetVertical, /* * A boolean value indicating whether client-side decorations are @@ -321,6 +322,11 @@ class LookAndFeel { return GetInt(IntID::UseOverlayScrollbars); } + static constexpr int32_t kDefaultTooltipOffset = 21; + static int32_t TooltipOffsetVertical() { + return GetInt(IntID::TooltipOffsetVertical, kDefaultTooltipOffset); + } + // Returns keyCode value of a modifier key which is used for accesskey. // Returns 0 if the platform doesn't support access key. static uint32_t GetMenuAccessKey(); diff --git a/widget/nsXPLookAndFeel.cpp b/widget/nsXPLookAndFeel.cpp index 9eabbd84b63c..e4739ca8deec 100644 --- a/widget/nsXPLookAndFeel.cpp +++ b/widget/nsXPLookAndFeel.cpp @@ -167,6 +167,7 @@ static const char sIntPrefs[][45] = { "ui.scrollbarFadeDuration", "ui.contextMenuOffsetVertical", "ui.contextMenuOffsetHorizontal", + "ui.tooltipOffsetVertical", "ui.GtkCSDAvailable", "ui.GtkCSDMinimizeButton", "ui.GtkCSDMaximizeButton", diff --git a/widget/windows/nsLookAndFeel.cpp b/widget/windows/nsLookAndFeel.cpp index 6122000c9eb2..bed28903eb73 100644 --- a/widget/windows/nsLookAndFeel.cpp +++ b/widget/windows/nsLookAndFeel.cpp @@ -36,6 +36,17 @@ static int32_t GetSystemParam(long flag, int32_t def) { return ::SystemParametersInfo(flag, 0, &value, 0) ? value : def; } +static int32_t GetTooltipOffsetVertical() { + static constexpr DWORD kDefaultCursorSize = 32; + const DWORD cursorSize = + GetSystemParam(MOZ_SPI_CURSORSIZE, kDefaultCursorSize); + if (cursorSize == kDefaultCursorSize) { + return LookAndFeel::kDefaultTooltipOffset; + } + return std::ceilf(float(LookAndFeel::kDefaultTooltipOffset) * + float(cursorSize) / float(kDefaultCursorSize)); +} + static bool SystemWantsDarkTheme() { if (nsUXThemeData::IsHighContrastOn()) { return LookAndFeel::IsDarkColor( @@ -523,6 +534,9 @@ nsresult nsLookAndFeel::NativeGetInt(IntID aID, int32_t& aResult) { case IntID::ContextMenuOffsetHorizontal: aResult = 2; break; + case IntID::TooltipOffsetVertical: + aResult = GetTooltipOffsetVertical(); + break; case IntID::SystemUsesDarkTheme: aResult = SystemWantsDarkTheme(); break; diff --git a/widget/windows/nsLookAndFeel.h b/widget/windows/nsLookAndFeel.h index d19aa91329f9..0ef38bfda528 100644 --- a/widget/windows/nsLookAndFeel.h +++ b/widget/windows/nsLookAndFeel.h @@ -40,6 +40,10 @@ #define SYS_COLOR_MAX 30 #define SYS_COLOR_COUNT (SYS_COLOR_MAX - SYS_COLOR_MIN + 1) +// Undocumented SPI, see bug 1712669 comment 4. +#define MOZ_SPI_CURSORSIZE 0x2028 +#define MOZ_SPI_SETCURSORSIZE 0x2029 + namespace mozilla::widget::WinRegistry { class KeyWatcher; } diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index 4e24e534c38d..b210381aa86d 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -78,6 +78,7 @@ #include #include "mozilla/widget/WinMessages.h" +#include "nsLookAndFeel.h" #include "nsWindow.h" #include "nsWindowTaskbarConcealer.h" #include "nsAppRunner.h" @@ -4939,10 +4940,12 @@ bool nsWindow::ProcessMessageInternal(UINT msg, WPARAM& wParam, LPARAM& lParam, case WM_SETTINGCHANGE: { if (wParam == SPI_SETCLIENTAREAANIMATION || - wParam == SPI_SETKEYBOARDDELAY || wParam == SPI_SETMOUSEVANISH) { + wParam == SPI_SETKEYBOARDDELAY || wParam == SPI_SETMOUSEVANISH || + wParam == MOZ_SPI_SETCURSORSIZE) { // These need to update LookAndFeel cached values. // They affect reduced motion settings / caret blink count / show - // pointer while typing, so no need to invalidate style / layout. + // pointer while typing / tooltip offset, so no need to invalidate style + // / layout. NotifyThemeChanged(widget::ThemeChangeKind::MediaQueriesOnly); break; }