From 2d300425aa2048f24de7447274a9496341b5ccda Mon Sep 17 00:00:00 2001 From: K4sum1 Date: Sun, 24 Nov 2024 09:38:01 -0600 Subject: [PATCH] Mostly fix XP theme The css @media thing seems to be broken (at least on 2003 with OCAPI), idk why. I think I did it right but I'm also r3tard. --- browser/themes/windows/browser.css | 10 + layout/style/nsMediaFeatures.cpp | 5 + .../components/style/gecko/media_features.rs | 2 + widget/windows/nsNativeThemeWin.cpp | 305 +++++++++++++++--- widget/windows/nsNativeThemeWin.h | 2 +- widget/windows/nsUXThemeData.cpp | 8 +- widget/windows/nsWindow.cpp | 44 ++- widget/windows/nsWindow.h | 2 + xpcom/ds/StaticAtoms.py | 2 + 9 files changed, 325 insertions(+), 55 deletions(-) diff --git a/browser/themes/windows/browser.css b/browser/themes/windows/browser.css index 7621ac1de29f2..042a3a5855b87 100644 --- a/browser/themes/windows/browser.css +++ b/browser/themes/windows/browser.css @@ -172,6 +172,16 @@ } } +/* add extra margin for unmaximized windows + on Win XP Luna themes to look consistent */ +@media not (-moz-windows-classic) { + @media (-moz-platform: windows-xp) { + :root[tabsintitlebar]:not([sizemode="maximized"]) .titlebar-buttonbox-container { + margin-top: 4px; + } + } +} + /* Window control buttons */ .titlebar-min { diff --git a/layout/style/nsMediaFeatures.cpp b/layout/style/nsMediaFeatures.cpp index 10dc4bf6df0c8..2324012817c6d 100644 --- a/layout/style/nsMediaFeatures.cpp +++ b/layout/style/nsMediaFeatures.cpp @@ -253,6 +253,11 @@ bool Gecko_MediaFeatures_MatchesPlatform(StylePlatform aPlatform) { #if defined(XP_WIN) case StylePlatform::Windows: return true; + case StylePlatform::WindowsWinXP: { + if (!IsVistaOrLater()) { + return true; + } + } #elif defined(ANDROID) case StylePlatform::Android: return true; diff --git a/servo/components/style/gecko/media_features.rs b/servo/components/style/gecko/media_features.rs index 06dba00b96702..ac211a7f18ec0 100644 --- a/servo/components/style/gecko/media_features.rs +++ b/servo/components/style/gecko/media_features.rs @@ -559,6 +559,8 @@ pub enum Platform { Macos, /// Matches any Windows version. Windows, + /// Matches only Windows XP. + WindowsWinXP, } fn eval_moz_platform(_: &Context, query_value: Option) -> bool { diff --git a/widget/windows/nsNativeThemeWin.cpp b/widget/windows/nsNativeThemeWin.cpp index 105014daa5126..a840dadcc48c7 100644 --- a/widget/windows/nsNativeThemeWin.cpp +++ b/widget/windows/nsNativeThemeWin.cpp @@ -42,6 +42,7 @@ #include "WinUtils.h" #include "ScrollbarDrawingWin.h" +using mozilla::IsVistaOrLater; using namespace mozilla; using namespace mozilla::gfx; using namespace mozilla::widget; @@ -332,6 +333,10 @@ static HRESULT DrawThemeBGRTLAware(HANDLE aTheme, HDC aHdc, int aPart, * aero basic max 0 2 1 2 * aero basic close 1 2 1 2 * + * xp theme min 0 2 0 2 + * xp theme max 0 2 1 2 + * xp theme close 1 2 2 2 + * * 'cold' button padding - generic button padding, should * be handled in css. * left top right bottom @@ -342,11 +347,16 @@ static HRESULT DrawThemeBGRTLAware(HANDLE aTheme, HDC aHdc, int aPart, * aero basic min 0 0 1 0 * aero basic max 1 0 0 0 * aero basic close 0 0 0 0 + * + * xp theme min 0 0 1 0 + * xp theme max 1 0 0 0 + * xp theme close 0 0 0 0 */ enum CaptionDesktopTheme { CAPTION_CLASSIC = 0, CAPTION_BASIC, + CAPTION_XPTHEME, }; enum CaptionButton { @@ -371,6 +381,8 @@ static void AddPaddingRect(LayoutDeviceIntSize* aSize, CaptionButton button) { RECT offset; if (!nsUXThemeData::IsAppThemed()) offset = buttonData[CAPTION_CLASSIC].hotPadding[button]; + else if (!IsVistaOrLater()) + offset = buttonData[CAPTION_XPTHEME].hotPadding[button]; else offset = buttonData[CAPTION_BASIC].hotPadding[button]; aSize->width += offset.left + offset.right; @@ -383,6 +395,8 @@ static void OffsetBackgroundRect(RECT& rect, CaptionButton button) { RECT offset; if (!nsUXThemeData::IsAppThemed()) offset = buttonData[CAPTION_CLASSIC].hotPadding[button]; + else if (!IsVistaOrLater()) + offset = buttonData[CAPTION_XPTHEME].hotPadding[button]; else offset = buttonData[CAPTION_BASIC].hotPadding[button]; rect.left += offset.left; @@ -428,7 +442,9 @@ static const double kProgressDeterminateTimeSpan = 3.0; static const double kProgressIndeterminateTimeSpan = 5.0; // The width of the overlay used to animate the horizontal progress bar (Vista // and later). -static const int32_t kProgressHorizontalOverlaySize = 120; +static const int32_t kProgressHorizontalVistaOverlaySize = 120; +// The width of the overlay used for the horizontal indeterminate progress bars on XP. +static const int32_t kProgressHorizontalXPOverlaySize = 55; // The height of the overlay used to animate the vertical progress bar (Vista // and later). static const int32_t kProgressVerticalOverlaySize = 45; @@ -444,7 +460,17 @@ static const int32_t kProgressClassicOverlaySize = 40; * progress bars based on os and orientation. */ static int32_t GetProgressOverlayStyle(bool aIsVertical) { - return aIsVertical ? PP_MOVEOVERLAYVERT : PP_MOVEOVERLAY; + if (aIsVertical) { + if (IsVistaOrLater()) { + return PP_MOVEOVERLAYVERT; + } + return PP_CHUNKVERT; + } else { + if (IsVistaOrLater()) { + return PP_MOVEOVERLAY; + } + return PP_CHUNK; + } } /* @@ -453,11 +479,14 @@ static int32_t GetProgressOverlayStyle(bool aIsVertical) { * and vista pulse overlays. */ static int32_t GetProgressOverlaySize(bool aIsVertical, bool aIsIndeterminate) { - if (aIsVertical) { - return aIsIndeterminate ? kProgressVerticalIndeterminateOverlaySize - : kProgressVerticalOverlaySize; + if (IsVistaOrLater()) { + if (aIsVertical) { + return aIsIndeterminate ? kProgressVerticalIndeterminateOverlaySize + : kProgressVerticalOverlaySize; + } + return kProgressHorizontalVistaOverlaySize; } - return kProgressHorizontalOverlaySize; + return kProgressHorizontalXPOverlaySize; } /* @@ -541,6 +570,84 @@ RECT nsNativeThemeWin::CalculateProgressOverlayRect(nsIFrame* aFrame, return overlayRect; } +/* + * DrawChunkProgressMeter - renders an xp style chunked progress meter. Called + * by DrawProgressMeter. + * + * @param aTheme progress theme handle + * @param aHdc hdc returned by gfxWindowsNativeDrawing + * @param aPart the PP_X progress part + * @param aState the theme state + * @param aFrame the elements frame + * @param aWidgetRect bounding rect for the widget + * @param aClipRect dirty rect that needs drawing. + * @param aAppUnits app units per device pixel + * @param aIsIndeterm is an indeterminate progress? + * @param aIsVertical render a vertical progress? + * @param aIsRtl direction is rtl + */ +static void +DrawChunkProgressMeter(HTHEME aTheme, HDC aHdc, int aPart, + int aState, nsIFrame* aFrame, RECT* aWidgetRect, + RECT* aClipRect, gfxFloat aAppUnits, bool aIsIndeterm, + bool aIsVertical, bool aIsRtl) +{ + NS_ASSERTION(aTheme, "Bad theme."); + NS_ASSERTION(aHdc, "Bad hdc."); + NS_ASSERTION(aWidgetRect, "Bad rect."); + NS_ASSERTION(aClipRect, "Bad clip rect."); + NS_ASSERTION(aFrame, "Bad frame."); + // For horizontal meters, the theme lib paints the right graphic but doesn't + // paint the chunks, so we do that manually. For vertical meters, the theme + // library draws everything correctly. + if (aIsVertical) { + DrawThemeBackground(aTheme, aHdc, aPart, aState, aWidgetRect, aClipRect); + return; + } + // query for the proper chunk metrics + int chunkSize, spaceSize; + if (FAILED(GetThemeMetric(aTheme, aHdc, aPart, aState, + TMT_PROGRESSCHUNKSIZE, &chunkSize)) || + FAILED(GetThemeMetric(aTheme, aHdc, aPart, aState, + TMT_PROGRESSSPACESIZE, &spaceSize))) { + DrawThemeBackground(aTheme, aHdc, aPart, aState, aWidgetRect, aClipRect); + return; + } + // render chunks + if (!aIsRtl || aIsIndeterm) { + for (int chunk = aWidgetRect->left; chunk <= aWidgetRect->right; + chunk += (chunkSize+spaceSize)) { + if (!aIsIndeterm && ((chunk + chunkSize) > aWidgetRect->right)) { + // aWidgetRect->right represents the end of the meter. Partial blocks + // don't get rendered with one exception, so exit here if we don't have + // a full chunk to draw. + // The above is true *except* when the meter is at 100% fill, in which + // case Windows renders any remaining partial block. Query the parent + // frame to find out if we're at 100%. + if (!IsProgressMeterFilled(aFrame)) { + break; + } + } + RECT bounds = + { chunk, aWidgetRect->top, chunk + chunkSize, aWidgetRect->bottom }; + DrawThemeBackground(aTheme, aHdc, aPart, aState, &bounds, aClipRect); + } + } else { + // rtl needs to grow in the opposite direction to look right. + for (int chunk = aWidgetRect->right; chunk >= aWidgetRect->left; + chunk -= (chunkSize+spaceSize)) { + if ((chunk - chunkSize) < aWidgetRect->left) { + if (!IsProgressMeterFilled(aFrame)) { + break; + } + } + RECT bounds = + { chunk - chunkSize, aWidgetRect->top, chunk, aWidgetRect->bottom }; + DrawThemeBackground(aTheme, aHdc, aPart, aState, &bounds, aClipRect); + } + } +} + /* * DrawProgressMeter - render an appropriate progress meter based on progress * meter style, orientation, and os. Note, this does not render the underlying @@ -558,7 +665,7 @@ RECT nsNativeThemeWin::CalculateProgressOverlayRect(nsIFrame* aFrame, */ void nsNativeThemeWin::DrawThemedProgressMeter( nsIFrame* aFrame, StyleAppearance aAppearance, HANDLE aTheme, HDC aHdc, - int aPart, int aState, RECT* aWidgetRect, RECT* aClipRect) { + int aPart, int aState, RECT* aWidgetRect, RECT* aClipRect, gfxFloat aAppUnits) { if (!aFrame || !aTheme || !aHdc) return; NS_ASSERTION(aWidgetRect, "bad rect pointer"); @@ -567,6 +674,12 @@ void nsNativeThemeWin::DrawThemedProgressMeter( RECT adjWidgetRect, adjClipRect; adjWidgetRect = *aWidgetRect; adjClipRect = *aClipRect; + if (!IsVistaOrLater()) { + // Adjust clipping out by one pixel. XP progress meters are inset, + // Vista+ are not. + InflateRect(&adjWidgetRect, 1, 1); + InflateRect(&adjClipRect, 1, 1); + } nsIFrame* parentFrame = aFrame->GetParent(); if (!parentFrame) { @@ -580,12 +693,19 @@ void nsNativeThemeWin::DrawThemedProgressMeter( bool indeterminate = elementState.HasState(ElementState::INDETERMINATE); bool animate = indeterminate; - // Vista and up progress meter is fill style, rendered here. We render - // the pulse overlay in the follow up section below. - DrawThemeBackground(aTheme, aHdc, aPart, aState, &adjWidgetRect, - &adjClipRect); - if (!IsProgressMeterFilled(aFrame)) { - animate = true; + if (IsVistaOrLater()) { + // Vista and up progress meter is fill style, rendered here. We render + // the pulse overlay in the follow up section below. + DrawThemeBackground(aTheme, aHdc, aPart, aState, + &adjWidgetRect, &adjClipRect); + if (!IsProgressMeterFilled(aFrame)) { + animate = true; + } + } else if (!indeterminate) { + // XP progress meters are 'chunk' style. + DrawChunkProgressMeter(aTheme, aHdc, aPart, aState, aFrame, + &adjWidgetRect, &adjClipRect, aAppUnits, + indeterminate, vertical, IsFrameRTL(aFrame)); } if (animate) { @@ -593,8 +713,14 @@ void nsNativeThemeWin::DrawThemedProgressMeter( int32_t overlayPart = GetProgressOverlayStyle(vertical); RECT overlayRect = CalculateProgressOverlayRect( aFrame, &adjWidgetRect, vertical, indeterminate, false); - DrawThemeBackground(aTheme, aHdc, overlayPart, aState, &overlayRect, - &adjClipRect); + if (IsVistaOrLater()) { + DrawThemeBackground(aTheme, aHdc, overlayPart, aState, &overlayRect, + &adjClipRect); + } else { + DrawChunkProgressMeter(aTheme, aHdc, overlayPart, aState, aFrame, + &overlayRect, &adjClipRect, aAppUnits, + indeterminate, vertical, IsFrameRTL(aFrame)); + } if (!QueueAnimatedContentForRefresh(aFrame->GetContent(), 60)) { NS_WARNING("unable to animate progress widget!"); @@ -706,6 +832,14 @@ nsresult nsNativeThemeWin::GetCachedMinimumWidgetSize( mozilla::Maybe nsNativeThemeWin::GetThemeClass( StyleAppearance aAppearance) { + if (!IsVistaOrLater()) { + // On XP or earlier, render dropdowns as textfields; + // doing it the right way works fine with the MS themes, + // but breaks on a lot of custom themes (presumably because MS + // apps do the textfield border business as well). + if (aAppearance == StyleAppearance::Menulist) + aAppearance = StyleAppearance::MenulistText; + } switch (aAppearance) { case StyleAppearance::Button: case StyleAppearance::Radio: @@ -719,7 +853,9 @@ mozilla::Maybe nsNativeThemeWin::GetThemeClass( case StyleAppearance::FocusOutline: return Some(eUXEdit); case StyleAppearance::Tooltip: - return Some(eUXTooltip); + // XP/2K3 should force a classic treatment of tooltips + return !IsVistaOrLater() ? + Nothing() : Some(eUXTooltip); case StyleAppearance::Toolbox: return Some(eUXRebar); case StyleAppearance::MozWinMediaToolbox: @@ -854,6 +990,11 @@ nsresult nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, StyleAppearance aAppearance, int32_t& aPart, int32_t& aState) { + if (!IsVistaOrLater()) { + if (aAppearance == StyleAppearance::Menulist) + aAppearance = StyleAppearance::MenulistText; + } + switch (aAppearance) { case StyleAppearance::Button: { aPart = BP_BUTTON; @@ -922,6 +1063,7 @@ nsresult nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, case StyleAppearance::Textarea: { ElementState elementState = GetContentState(aFrame, aAppearance); + if (IsVistaOrLater()) { /* Note: the NOSCROLL type has a rounded corner in each corner. The more * specific HSCROLL, VSCROLL, HVSCROLL types have side and/or top/bottom * edges rendered as straight horizontal lines with sharp corners to @@ -945,13 +1087,30 @@ nsresult nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, } else { aState = TFS_EDITBORDER_NORMAL; } + } else { + aPart = TFP_TEXTFIELD; + + if (!aFrame) + aState = TS_NORMAL; + else if (elementState.HasState(ElementState::DISABLED)) + aState = TS_DISABLED; + else if (IsReadOnly(aFrame)) + aState = TFS_READONLY; + else + aState = StandardGetState(aFrame, aAppearance, true); + } return NS_OK; } case StyleAppearance::FocusOutline: { - // XXX the EDITBORDER values don't respect DTBG_OMITCONTENT - aPart = TFP_TEXTFIELD; // TFP_EDITBORDER_NOSCROLL; - aState = TS_FOCUSED; // TFS_EDITBORDER_FOCUSED; + if (IsVistaOrLater()) { + // XXX the EDITBORDER values don't respect DTBG_OMITCONTENT + aPart = TFP_TEXTFIELD; //TFP_EDITBORDER_NOSCROLL; + aState = TS_FOCUSED; //TFS_EDITBORDER_FOCUSED; + } else { + aPart = TFP_TEXTFIELD; + aState = TS_FOCUSED; + } return NS_OK; } case StyleAppearance::Tooltip: { @@ -968,9 +1127,11 @@ nsresult nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, case StyleAppearance::Progresschunk: { nsIFrame* parentFrame = aFrame->GetParent(); if (IsVerticalProgress(parentFrame)) { - aPart = PP_FILLVERT; + aPart = IsVistaOrLater() ? + PP_FILLVERT : PP_CHUNKVERT; } else { - aPart = PP_FILL; + aPart = IsVistaOrLater() ? + PP_FILL : PP_CHUNK; } aState = PBBVS_NORMAL; @@ -1033,7 +1194,8 @@ nsresult nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, aState += TS_ACTIVE; else if (eventState.HasState(ElementState::HOVER)) aState += TS_HOVER; - else if (parentState.HasState(ElementState::HOVER)) + else if (IsVistaOrLater() && + parentState.HasState(ElementState::HOVER)) aState = (int(aAppearance) - int(StyleAppearance::ScrollbarbuttonUp)) + SP_BUTTON_IMPLICIT_HOVER_BASE; @@ -1136,7 +1298,14 @@ nsresult nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, case StyleAppearance::MozWinBrowsertabbarToolbox: case StyleAppearance::Statusbar: { aState = 0; - aPart = RP_BACKGROUND; + if (IsVistaOrLater()) { + // On vista, they have a part + aPart = RP_BACKGROUND; + } else { + // Otherwise, they don't. (But I bet + // RP_BACKGROUND would work here, too); + aPart = 0; + } return NS_OK; } case StyleAppearance::Toolbar: { @@ -1266,7 +1435,8 @@ nsresult nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, aFrame = parentFrame; ElementState elementState = GetContentState(aFrame, aAppearance); - aPart = CBP_DROPMARKER_VISTA; + aPart = IsVistaOrLater() ? + CBP_DROPMARKER_VISTA : CBP_DROPMARKER; // For HTML controls with author styling, we should fall // back to the old dropmarker style to avoid clashes with @@ -1283,7 +1453,7 @@ nsresult nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, if (nsComboboxControlFrame* ccf = do_QueryFrame(aFrame)) { isOpen = ccf->IsDroppedDown(); - if (isOpen) { + if (isOpen && IsVistaOrLater()) { /* Hover is propagated, but we need to know whether we're hovering * just the combobox frame, not the dropdown frame. But, we can't get * that information, since hover is on the content node, and they @@ -1759,7 +1929,7 @@ nsNativeThemeWin::DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame, SetPixel(hdc, widgetRect.left, widgetRect.bottom - 1, color); } else if (aAppearance == StyleAppearance::Progresschunk) { DrawThemedProgressMeter(aFrame, aAppearance, theme, hdc, part, state, - &widgetRect, &clipRect); + &widgetRect, &clipRect, p2a); } else if (aAppearance == StyleAppearance::FocusOutline) { // Inflate 'widgetRect' with the focus outline size. LayoutDeviceIntMargin border = GetWidgetBorder( @@ -2034,6 +2204,7 @@ bool nsNativeThemeWin::GetWidgetPadding(nsDeviceContext* aContext, * Instead, we add 2px padding for the contents and fix this. (Used to be 1px * added, see bug 430212) */ + if (IsVistaOrLater()) { if (aAppearance == StyleAppearance::NumberInput || aAppearance == StyleAppearance::PasswordInput || aAppearance == StyleAppearance::Textfield || @@ -2054,6 +2225,7 @@ bool nsNativeThemeWin::GetWidgetPadding(nsDeviceContext* aContext, ScaleForFrameDPI(aResult, aFrame); return ok; } + } int32_t right, left, top, bottom; right = left = top = bottom = 0; @@ -2128,17 +2300,19 @@ bool nsNativeThemeWin::GetWidgetOverflow(nsDeviceContext* aContext, * and bottom so that they overlap the dropdown's border like they're * supposed to. */ - if (aAppearance == StyleAppearance::MenulistButton && - IsHTMLContent(aFrame) && - !IsWidgetStyled(aFrame->GetParent()->PresContext(), - aFrame->GetParent(), - StyleAppearance::Menulist)) - { - int32_t p2a = aContext->AppUnitsPerDevPixel(); - /* Note: no overflow on the left */ - nsMargin m(p2a, p2a, p2a, 0); - aOverflowRect->Inflate (m); - return true; + if (IsVistaOrLater()) { + if (aAppearance == StyleAppearance::MenulistButton && + IsHTMLContent(aFrame) && + !IsWidgetStyled(aFrame->GetParent()->PresContext(), + aFrame->GetParent(), + StyleAppearance::Menulist)) + { + int32_t p2a = aContext->AppUnitsPerDevPixel(); + /* Note: no overflow on the left */ + nsMargin m(p2a, p2a, p2a, 0); + aOverflowRect->Inflate (m); + return true; + } } #endif @@ -2206,21 +2380,42 @@ LayoutDeviceIntSize nsNativeThemeWin::GetMinimumWidgetSize( // window w/buttons when it's visible. nsWindow takes care of this and // stores that info in nsUXThemeData. SIZE sz = nsUXThemeData::GetCommandButtonMetrics(CMDBUTTONIDX_RESTORE); - LayoutDeviceIntSize result(sz.cx, sz.cy); - AddPaddingRect(&result, CAPTIONBUTTON_RESTORE); - return result; + // For XP, subtract 4 from system metrics dimensions. + if (!IsVistaOrLater()) { + LayoutDeviceIntSize result(sz.cx - 4, sz.cy - 4); + AddPaddingRect(&result, CAPTIONBUTTON_RESTORE); + return result; + } else { + LayoutDeviceIntSize result(sz.cx, sz.cy); + AddPaddingRect(&result, CAPTIONBUTTON_RESTORE); + return result; + } } case StyleAppearance::MozWindowButtonMinimize: { SIZE sz = nsUXThemeData::GetCommandButtonMetrics(CMDBUTTONIDX_MINIMIZE); LayoutDeviceIntSize result(sz.cx, sz.cy); - AddPaddingRect(&result, CAPTIONBUTTON_MINIMIZE); - return result; + if (!IsVistaOrLater()) { + LayoutDeviceIntSize result(sz.cx - 4, sz.cy - 4); + AddPaddingRect(&result, CAPTIONBUTTON_MINIMIZE); + return result; + } else { + LayoutDeviceIntSize result(sz.cx, sz.cy); + AddPaddingRect(&result, CAPTIONBUTTON_MINIMIZE); + return result; + } } case StyleAppearance::MozWindowButtonClose: { SIZE sz = nsUXThemeData::GetCommandButtonMetrics(CMDBUTTONIDX_CLOSE); LayoutDeviceIntSize result(sz.cx, sz.cy); - AddPaddingRect(&result, CAPTIONBUTTON_CLOSE); - return result; + if (!IsVistaOrLater()) { + LayoutDeviceIntSize result(sz.cx - 4, sz.cy - 4); + AddPaddingRect(&result, CAPTIONBUTTON_CLOSE); + return result; + } else { + LayoutDeviceIntSize result(sz.cx, sz.cy); + AddPaddingRect(&result, CAPTIONBUTTON_CLOSE); + return result; + } } case StyleAppearance::MozWindowTitlebar: @@ -2305,12 +2500,17 @@ LayoutDeviceIntSize nsNativeThemeWin::GetMinimumWidgetSize( break; case StyleAppearance::RangeThumb: { - LayoutDeviceIntSize result(12, 20); - if (!IsRangeHorizontal(aFrame)) { - std::swap(result.width, result.height); + // On Vista, GetThemePartAndState returns odd values for + // scale thumbs, so use a hardcoded size instead. + if (IsVistaOrLater()) { + LayoutDeviceIntSize result(12, 20); + if (!IsRangeHorizontal(aFrame)) { + std::swap(result.width, result.height); + } + ScaleForFrameDPI(&result, aFrame); + return result; } - ScaleForFrameDPI(&result, aFrame); - return result; + break; } case StyleAppearance::Scrollcorner: { @@ -2400,6 +2600,13 @@ bool nsNativeThemeWin::WidgetAttributeChangeRequiresRepaint( return true; } + // On Vista, the scrollbar buttons need to change state when the track has/doesn't have hover + if (!IsVistaOrLater() && + (aAppearance == StyleAppearance::ScrollbarVertical || + aAppearance == StyleAppearance::ScrollbarHorizontal)) { + return false; + } + return Theme::WidgetAttributeChangeRequiresRepaint(aAppearance, aAttribute); } diff --git a/widget/windows/nsNativeThemeWin.h b/widget/windows/nsNativeThemeWin.h index 108096c5de1de..6d804f4ef4f2f 100644 --- a/widget/windows/nsNativeThemeWin.h +++ b/widget/windows/nsNativeThemeWin.h @@ -125,7 +125,7 @@ class nsNativeThemeWin : public Theme { bool aIsClassic); void DrawThemedProgressMeter(nsIFrame* aFrame, StyleAppearance aAppearance, HANDLE aTheme, HDC aHdc, int aPart, int aState, - RECT* aWidgetRect, RECT* aClipRect); + RECT* aWidgetRect, RECT* aClipRect, gfxFloat aAppUnits); [[nodiscard]] LayoutDeviceIntMargin GetCachedWidgetBorder( HANDLE aTheme, nsUXThemeClass aThemeClass, StyleAppearance aAppearance, diff --git a/widget/windows/nsUXThemeData.cpp b/widget/windows/nsUXThemeData.cpp index 0532117293a60..f9eccb8a73e92 100644 --- a/widget/windows/nsUXThemeData.cpp +++ b/widget/windows/nsUXThemeData.cpp @@ -172,8 +172,10 @@ void nsUXThemeData::EnsureCommandButtonMetrics() { sCommandButtonMetrics[1].cy = sCommandButtonMetrics[2].cy = sCommandButtonMetrics[0].cy; - // Trigger a refresh on the next layout. - sTitlebarInfoPopulatedAero = sTitlebarInfoPopulatedThemed = false; + // Use system metrics for pre-vista, otherwise trigger a + // refresh on the next layout. + sTitlebarInfoPopulatedAero = sTitlebarInfoPopulatedThemed = + !IsVistaOrLater(); } // static @@ -330,7 +332,7 @@ bool nsUXThemeData::IsHighContrastOn() { return sIsHighContrastOn; } // static void nsUXThemeData::UpdateNativeThemeInfo() { // Trigger a refresh of themed button metrics if needed - sTitlebarInfoPopulatedThemed = false; + sTitlebarInfoPopulatedThemed = !IsVistaOrLater(); sIsDefaultWindowsTheme = false; sThemeId = WindowsTheme::Generic; diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index 7f174345152a3..2a05a5962f50a 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -338,6 +338,9 @@ UINT nsWindow::sHookTimerId = 0; // input. POINT nsWindow::sLastMouseMovePoint = {0}; +// Trim heap on minimize. (initialized, but still true.) +//int nsWindow::sTrimOnMinimize = 2; + bool nsWindow::sIsRestoringSession = false; bool nsWindow::sTouchInjectInitialized = false; @@ -960,7 +963,7 @@ nsresult nsWindow::Create(nsIWidget* aParent, const LayoutDeviceIntRect& aRect, // When window is PiP window on Windows7, WS_EX_COMPOSITED is set to suppress // flickering during resizing with hardware acceleration. bool isPIPWindow = aInitData && aInitData->mPIPWindow; - if (isPIPWindow && !IsWin8OrLater() && + if (isPIPWindow && IsVistaOrLater() && !IsWin8OrLater() && gfxConfig::IsEnabled(gfx::Feature::HW_COMPOSITING) && WidgetTypeSupportsAcceleration()) { desiredStyles.ex |= WS_EX_COMPOSITED; @@ -1210,6 +1213,19 @@ nsresult nsWindow::Create(nsIWidget* aParent, const LayoutDeviceIntRect& aRect, mDefaultIMC.Init(this); IMEHandler::InitInputContext(this, mInputContext); + // If the internal variable set by the config.trim_on_minimize pref has not + // been initialized, and if this is the hidden window (conveniently created + // before any visible windows, and after the profile has been initialized), + // do some initialization work. +// if (sTrimOnMinimize == 2 && mWindowType == eWindowType_invisible) { + // Our internal trim prevention logic is effective on 2K/XP at maintaining + // the working set when windows are minimized, but on Vista and up it has + // little to no effect. Since this feature has been the source of numerous + // bugs over the years, disable it (sTrimOnMinimize=1) on Vista and up. +// sTrimOnMinimize = Preferences::GetBool("config.trim_on_minimize", +// IsVistaOrLater() ? 1 : 0); +// } + // Query for command button metric data for rendering the titlebar. We // only do this once on the first window that has an actual titlebar if (ShouldCacheTitleBarInfo(mWindowType, mBorderStyle)) { @@ -1786,7 +1802,7 @@ bool nsWindow::IsVisible() const { return mIsVisible; } // operations. // XXX this is apparently still needed in Windows 7 and later void nsWindow::ClearThemeRegion() { - if (!HasGlass() && + if (IsVistaOrLater() && !HasGlass() && (mWindowType == WindowType::Popup && (mPopupType == PopupType::Tooltip || mPopupType == PopupType::Panel))) { SetWindowRgn(mWnd, nullptr, false); @@ -6857,6 +6873,30 @@ void nsWindow::OnWindowPosChanged(WINDOWPOS* wp) { } } +// static +void nsWindow::ActivateOtherWindowHelper(HWND aWnd) { + // Find the next window that is enabled, visible, and not minimized. + HWND hwndBelow = ::GetNextWindow(aWnd, GW_HWNDNEXT); + while (hwndBelow && + (!::IsWindowEnabled(hwndBelow) || !::IsWindowVisible(hwndBelow) || + ::IsIconic(hwndBelow))) { + hwndBelow = ::GetNextWindow(hwndBelow, GW_HWNDNEXT); + } + + // Push ourselves to the bottom of the stack, then activate the + // next window. + ::SetWindowPos(aWnd, HWND_BOTTOM, 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); + if (hwndBelow) ::SetForegroundWindow(hwndBelow); + + // Play the minimize sound while we're here, since that is also + // forgotten when we use SW_SHOWMINIMIZED. + /*nsCOMPtr sound(do_CreateInstance("@mozilla.org/sound;1")); + if (sound) { + sound->PlaySystemSound(NS_LITERAL_STRING("Minimize")); + }*/ +} + void nsWindow::OnWindowPosChanging(WINDOWPOS* info) { // Update non-client margins if the frame size is changing, and let the // browser know we are changing size modes, so alternative css can kick in. diff --git a/widget/windows/nsWindow.h b/widget/windows/nsWindow.h index 531fb377a7887..8a14b1768f777 100644 --- a/widget/windows/nsWindow.h +++ b/widget/windows/nsWindow.h @@ -686,6 +686,7 @@ class nsWindow final : public nsBaseWidget { static HWND WindowAtMouse(); static bool IsTopLevelMouseExit(HWND aWnd); LayoutDeviceIntRegion GetRegionToPaint(const PAINTSTRUCT& ps, HDC aDC) const; + static void ActivateOtherWindowHelper(HWND aWnd); nsIWidgetListener* GetPaintListener(); void AddWindowOverlayWebRenderCommands( @@ -742,6 +743,7 @@ class nsWindow final : public nsBaseWidget { static bool sJustGotDeactivate; static bool sJustGotActivate; static bool sIsInMouseCapture; +// static int sTrimOnMinimize; static bool sIsRestoringSession; // Message postponement hack. See the definition-site of diff --git a/xpcom/ds/StaticAtoms.py b/xpcom/ds/StaticAtoms.py index 21296faac805d..5cb05c960ed3a 100644 --- a/xpcom/ds/StaticAtoms.py +++ b/xpcom/ds/StaticAtoms.py @@ -2261,6 +2261,8 @@ Atom("forcemessagemanager", "forcemessagemanager"), Atom("initialBrowsingContextGroupId", "initialBrowsingContextGroupId"), Atom("manualactiveness", "manualactiveness"), + # Windows XP media query name because I'm too r3tard to do it properly + Atom("windows_winxp", "windows-winxp"), # Names for system metrics. Atom("_moz_bool_pref", "-moz-bool-pref"), Atom("_moz_scrollbar_start_backward", "-moz-scrollbar-start-backward"),