From 112fc3532b72cf0fe3737b8fd7507c65f90cf375 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Tue, 12 Jul 2022 18:19:24 -0400 Subject: [PATCH] app_server: Basic scaling for window borders. This code is quite convoluted and very much in need of refactoring, but this solution works well enough for the time being. It does not look quite right at higher resolutions (borders come out darker than they do at the default resolution), but at least the borders are now the correct size instead of a constant one. The resize nub drawing code also hasn't yet been updated, so while it draws the gradient over the full resize area and responds to clicks, the "checkerboard" pattern is drawn at a fixed small size still. Nonetheless, this is a significant improvement. --- .../app/decorator/DefaultDecorator.cpp | 102 ++++++++++-------- src/servers/app/decorator/TabDecorator.cpp | 40 ++++--- src/servers/app/decorator/TabDecorator.h | 1 + 3 files changed, 84 insertions(+), 59 deletions(-) diff --git a/src/servers/app/decorator/DefaultDecorator.cpp b/src/servers/app/decorator/DefaultDecorator.cpp index f76fb68acf..78d549adf4 100644 --- a/src/servers/app/decorator/DefaultDecorator.cpp +++ b/src/servers/app/decorator/DefaultDecorator.cpp @@ -52,9 +52,6 @@ #endif -static const float kBorderResizeLength = 22.0; - - static inline uint8 blend_color_value(uint8 a, uint8 b, float position) { @@ -209,6 +206,9 @@ DefaultDecorator::_DrawFrame(BRect rect) if (fBorderWidth <= 0) return; + // TODO: While this works, it does not look so crisp at higher resolutions. +#define COLORS_INDEX(i, borderWidth, nominalLimit) ((float(i) / float(borderWidth)) * nominalLimit) + // Draw the border frame BRect border = BRect(fTopBorder.LeftTop(), fBottomBorder.RightBottom()); switch ((int)fTopTab->look) { @@ -221,20 +221,23 @@ DefaultDecorator::_DrawFrame(BRect rect) ComponentColors colors; _GetComponentColors(COMPONENT_TOP_BORDER, colors, fTopTab); - for (int8 i = 0; i < 5; i++) { + for (int8 i = 0; i < fBorderWidth; i++) { + const int8 colorsIndex = COLORS_INDEX(i, fBorderWidth, 5); fDrawingEngine->StrokeLine( BPoint(border.left + i, border.top + i), - BPoint(border.right - i, border.top + i), colors[i]); + BPoint(border.right - i, border.top + i), + colors[colorsIndex]); } if (fTitleBarRect.IsValid()) { // grey along the bottom of the tab // (overwrites "white" from frame) - fDrawingEngine->StrokeLine( - BPoint(fTitleBarRect.left + 2, - fTitleBarRect.bottom + 1), - BPoint(fTitleBarRect.right - 2, - fTitleBarRect.bottom + 1), - colors[2]); + const int overdraw = ceilf(fBorderWidth / 5.0f); + for (int i = 1; i <= overdraw; i++) { + fDrawingEngine->StrokeLine( + BPoint(fTitleBarRect.left + 2, fTitleBarRect.bottom + i), + BPoint(fTitleBarRect.right - 2, fTitleBarRect.bottom + i), + colors[2]); + } } } // left @@ -242,10 +245,12 @@ DefaultDecorator::_DrawFrame(BRect rect) ComponentColors colors; _GetComponentColors(COMPONENT_LEFT_BORDER, colors, fTopTab); - for (int8 i = 0; i < 5; i++) { + for (int8 i = 0; i < fBorderWidth; i++) { + const int8 colorsIndex = COLORS_INDEX(i, fBorderWidth, 5); fDrawingEngine->StrokeLine( BPoint(border.left + i, border.top + i), - BPoint(border.left + i, border.bottom - i), colors[i]); + BPoint(border.left + i, border.bottom - i), + colors[colorsIndex]); } } // bottom @@ -253,11 +258,12 @@ DefaultDecorator::_DrawFrame(BRect rect) ComponentColors colors; _GetComponentColors(COMPONENT_BOTTOM_BORDER, colors, fTopTab); - for (int8 i = 0; i < 5; i++) { + for (int8 i = 0; i < fBorderWidth; i++) { + const int8 colorsIndex = COLORS_INDEX(i, fBorderWidth, 5); fDrawingEngine->StrokeLine( BPoint(border.left + i, border.bottom - i), BPoint(border.right - i, border.bottom - i), - colors[(4 - i) == 4 ? 5 : (4 - i)]); + colors[(4 - colorsIndex) == 4 ? 5 : (4 - colorsIndex)]); } } // right @@ -265,11 +271,12 @@ DefaultDecorator::_DrawFrame(BRect rect) ComponentColors colors; _GetComponentColors(COMPONENT_RIGHT_BORDER, colors, fTopTab); - for (int8 i = 0; i < 5; i++) { + for (int8 i = 0; i < fBorderWidth; i++) { + const int8 colorsIndex = COLORS_INDEX(i, fBorderWidth, 5); fDrawingEngine->StrokeLine( BPoint(border.right - i, border.top + i), BPoint(border.right - i, border.bottom - i), - colors[(4 - i) == 4 ? 5 : (4 - i)]); + colors[(4 - colorsIndex) == 4 ? 5 : (4 - colorsIndex)]); } } break; @@ -283,20 +290,23 @@ DefaultDecorator::_DrawFrame(BRect rect) ComponentColors colors; _GetComponentColors(COMPONENT_TOP_BORDER, colors, fTopTab); - for (int8 i = 0; i < 3; i++) { + for (int8 i = 0; i < fBorderWidth; i++) { + const int8 colorsIndex = COLORS_INDEX(i, fBorderWidth, 3); fDrawingEngine->StrokeLine( BPoint(border.left + i, border.top + i), BPoint(border.right - i, border.top + i), - colors[i * 2]); + colors[colorsIndex * 2]); } if (fTitleBarRect.IsValid() && fTopTab->look != kLeftTitledWindowLook) { // grey along the bottom of the tab // (overwrites "white" from frame) - fDrawingEngine->StrokeLine( - BPoint(fTitleBarRect.left + 2, - fTitleBarRect.bottom + 1), - BPoint(fTitleBarRect.right - 2, - fTitleBarRect.bottom + 1), colors[2]); + const int overdraw = ceilf(fBorderWidth / 5.0f); + for (int i = 1; i <= overdraw; i++) { + fDrawingEngine->StrokeLine( + BPoint(fTitleBarRect.left + 2, fTitleBarRect.bottom + i), + BPoint(fTitleBarRect.right - 2, fTitleBarRect.bottom + i), + colors[2]); + } } } // left @@ -304,11 +314,12 @@ DefaultDecorator::_DrawFrame(BRect rect) ComponentColors colors; _GetComponentColors(COMPONENT_LEFT_BORDER, colors, fTopTab); - for (int8 i = 0; i < 3; i++) { + for (int8 i = 0; i < fBorderWidth; i++) { + const int8 colorsIndex = COLORS_INDEX(i, fBorderWidth, 3); fDrawingEngine->StrokeLine( BPoint(border.left + i, border.top + i), BPoint(border.left + i, border.bottom - i), - colors[i * 2]); + colors[colorsIndex * 2]); } if (fTopTab->look == kLeftTitledWindowLook && fTitleBarRect.IsValid()) { @@ -326,11 +337,12 @@ DefaultDecorator::_DrawFrame(BRect rect) ComponentColors colors; _GetComponentColors(COMPONENT_BOTTOM_BORDER, colors, fTopTab); - for (int8 i = 0; i < 3; i++) { + for (int8 i = 0; i < fBorderWidth; i++) { + const int8 colorsIndex = COLORS_INDEX(i, fBorderWidth, 3); fDrawingEngine->StrokeLine( BPoint(border.left + i, border.bottom - i), BPoint(border.right - i, border.bottom - i), - colors[(2 - i) == 2 ? 5 : (2 - i) * 2]); + colors[(2 - colorsIndex) == 2 ? 5 : (2 - colorsIndex) * 2]); } } // right @@ -338,11 +350,12 @@ DefaultDecorator::_DrawFrame(BRect rect) ComponentColors colors; _GetComponentColors(COMPONENT_RIGHT_BORDER, colors, fTopTab); - for (int8 i = 0; i < 3; i++) { + for (int8 i = 0; i < fBorderWidth; i++) { + const int8 colorsIndex = COLORS_INDEX(i, fBorderWidth, 3); fDrawingEngine->StrokeLine( BPoint(border.right - i, border.top + i), BPoint(border.right - i, border.bottom - i), - colors[(2 - i) == 2 ? 5 : (2 - i) * 2]); + colors[(2 - colorsIndex) == 2 ? 5 : (2 - colorsIndex) * 2]); } } break; @@ -393,22 +406,22 @@ DefaultDecorator::_DrawFrame(BRect rect) case kLeftTitledWindowLook: { if (!rect.Intersects(BRect( - fRightBorder.right - kBorderResizeLength, - fBottomBorder.bottom - kBorderResizeLength, + fRightBorder.right - fBorderResizeLength, + fBottomBorder.bottom - fBorderResizeLength, fRightBorder.right - 1, fBottomBorder.bottom - 1))) break; fDrawingEngine->StrokeLine( BPoint(fRightBorder.left, - fBottomBorder.bottom - kBorderResizeLength), + fBottomBorder.bottom - fBorderResizeLength), BPoint(fRightBorder.right - 1, - fBottomBorder.bottom - kBorderResizeLength), + fBottomBorder.bottom - fBorderResizeLength), colors[0]); fDrawingEngine->StrokeLine( - BPoint(fRightBorder.right - kBorderResizeLength, + BPoint(fRightBorder.right - fBorderResizeLength, fBottomBorder.top), - BPoint(fRightBorder.right - kBorderResizeLength, + BPoint(fRightBorder.right - fBorderResizeLength, fBottomBorder.bottom - 1), colors[0]); break; @@ -437,14 +450,15 @@ DefaultDecorator::_DrawResizeKnob(BRect rect, bool full, fDrawingEngine->FillRect(rect, gradient); - fDrawingEngine->StrokeLine(BPoint(x - 15, y - 15), - BPoint(x - 15, y - 2), colors[0]); - fDrawingEngine->StrokeLine(BPoint(x - 14, y - 14), - BPoint(x - 14, y - 1), colors[1]); - fDrawingEngine->StrokeLine(BPoint(x - 15, y - 15), - BPoint(x - 2, y - 15), colors[0]); - fDrawingEngine->StrokeLine(BPoint(x - 14, y - 14), - BPoint(x - 1, y - 14), colors[1]); + BPoint offset1(15, 15), offset2(14, 14); + fDrawingEngine->StrokeLine(BPoint(x, y) - offset1, + BPoint(x - offset1.x, y - 2), colors[0]); + fDrawingEngine->StrokeLine(BPoint(x, y) - offset2, + BPoint(x - offset2.x, y - 1), colors[1]); + fDrawingEngine->StrokeLine(BPoint(x, y) - offset1, + BPoint(x - 2, y - offset1.y), colors[0]); + fDrawingEngine->StrokeLine(BPoint(x, y) - offset2, + BPoint(x - 1, y - offset2.y), colors[1]); if (!full) return; diff --git a/src/servers/app/decorator/TabDecorator.cpp b/src/servers/app/decorator/TabDecorator.cpp index 1ebf7391f5..21317a5b85 100644 --- a/src/servers/app/decorator/TabDecorator.cpp +++ b/src/servers/app/decorator/TabDecorator.cpp @@ -163,8 +163,8 @@ TabDecorator::RegionAt(BPoint where, int32& tab) const || fTopTab->look == B_FLOATING_WINDOW_LOOK || fTopTab->look == B_MODAL_WINDOW_LOOK || fTopTab->look == kLeftTitledWindowLook)) { - BRect resizeRect(BPoint(fBottomBorder.right - kBorderResizeLength, - fBottomBorder.bottom - kBorderResizeLength), + BRect resizeRect(BPoint(fBottomBorder.right - fBorderResizeLength, + fBottomBorder.bottom - fBorderResizeLength), fBottomBorder.RightBottom()); if (resizeRect.Contains(where)) return REGION_RIGHT_BOTTOM_CORNER; @@ -235,6 +235,9 @@ TabDecorator::_DoLayout() bool hasTab = false; + // TODO: Put this computation somewhere more central! + const float scaleFactor = max_c(fDrawState.Font().Size() / 12.0f, 1.0f); + switch ((int)fTopTab->look) { case B_MODAL_WINDOW_LOOK: fBorderWidth = 5; @@ -259,6 +262,10 @@ TabDecorator::_DoLayout() fBorderWidth = 0; } + fBorderWidth *= scaleFactor; + fResizeKnobSize = kResizeKnobSize * scaleFactor; + fBorderResizeLength = kBorderResizeLength * scaleFactor; + // calculate left/top/right/bottom borders if (fBorderWidth > 0) { // NOTE: no overlapping, the left and right border rects @@ -286,8 +293,8 @@ TabDecorator::_DoLayout() // calculate resize rect if (fBorderWidth > 1) { - fResizeRect.Set(fBottomBorder.right - kResizeKnobSize, - fBottomBorder.bottom - kResizeKnobSize, fBottomBorder.right, + fResizeRect.Set(fBottomBorder.right - fResizeKnobSize, + fBottomBorder.bottom - fResizeKnobSize, fBottomBorder.right, fBottomBorder.bottom); } else { // no border or one pixel border (menus and such) @@ -360,15 +367,16 @@ TabDecorator::_DoTabLayout() fDrawState.Font().GetHeight(fontHeight); if (tab->look != kLeftTitledWindowLook) { + const float spacing = fBorderWidth * 1.4f; tabRect.Set(fFrame.left - fBorderWidth, fFrame.top - fBorderWidth - - ceilf(fontHeight.ascent + fontHeight.descent + 7.0), - ((fFrame.right - fFrame.left) < 35.0 ? - fFrame.left + 35.0 : fFrame.right) + fBorderWidth, + - ceilf(fontHeight.ascent + fontHeight.descent + spacing), + ((fFrame.right - fFrame.left) < (spacing * 5) ? + fFrame.left + (spacing * 5) : fFrame.right) + fBorderWidth, fFrame.top - fBorderWidth); } else { tabRect.Set(fFrame.left - fBorderWidth - - ceilf(fontHeight.ascent + fontHeight.descent + 5.0), + - ceilf(fontHeight.ascent + fontHeight.descent + fBorderWidth), fFrame.top - fBorderWidth, fFrame.left - fBorderWidth, fFrame.bottom + fBorderWidth); } @@ -608,9 +616,9 @@ TabDecorator::_ResizeBy(BPoint offset, BRegion* dirty) case B_MODAL_WINDOW_LOOK: case kLeftTitledWindowLook: // The bottom border resize line - realResizeRect.Set(fRightBorder.right - kBorderResizeLength, + realResizeRect.Set(fRightBorder.right - fBorderResizeLength, fBottomBorder.top, - fRightBorder.right - kBorderResizeLength, + fRightBorder.right - fBorderResizeLength, fBottomBorder.bottom - 1); // Old location dirty->Include(realResizeRect); @@ -620,9 +628,9 @@ TabDecorator::_ResizeBy(BPoint offset, BRegion* dirty) // The right border resize line realResizeRect.Set(fRightBorder.left, - fBottomBorder.bottom - kBorderResizeLength, + fBottomBorder.bottom - fBorderResizeLength, fRightBorder.right - 1, - fBottomBorder.bottom - kBorderResizeLength); + fBottomBorder.bottom - fBorderResizeLength); // Old location dirty->Include(realResizeRect); realResizeRect.OffsetBy(offset); @@ -916,7 +924,7 @@ TabDecorator::_GetFootprint(BRegion *region) if (fTopTab->look == B_DOCUMENT_WINDOW_LOOK) { // include the rectangular resize knob on the bottom right - float knobSize = kResizeKnobSize - fBorderWidth; + float knobSize = fResizeKnobSize - fBorderWidth; region->Include(BRect(fFrame.right - knobSize, fFrame.bottom - knobSize, fFrame.right, fFrame.bottom)); } @@ -1058,8 +1066,10 @@ TabDecorator::_LayoutTabItems(Decorator::Tab* _tab, const BRect& tabRect) float TabDecorator::_DefaultTextOffset() const { - return (fTopTab->look == B_FLOATING_WINDOW_LOOK - || fTopTab->look == kLeftTitledWindowLook) ? 10 : 18; + if (fTopTab->look == B_FLOATING_WINDOW_LOOK + || fTopTab->look == kLeftTitledWindowLook) + return int32(fBorderWidth * 3.4f); + return int32(fBorderWidth * 3.6f); } diff --git a/src/servers/app/decorator/TabDecorator.h b/src/servers/app/decorator/TabDecorator.h index ef3a5de0a2..efb4ef8180 100644 --- a/src/servers/app/decorator/TabDecorator.h +++ b/src/servers/app/decorator/TabDecorator.h @@ -137,6 +137,7 @@ protected: protected: BRegion fTabsRegion; BRect fOldMovingTab; + float fBorderResizeLength, fResizeKnobSize; rgb_color fFocusFrameColor;