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.
This commit is contained in:
Augustin Cavalier 2022-07-12 18:19:24 -04:00
parent 644fa4bf7b
commit 112fc3532b
3 changed files with 84 additions and 59 deletions

View File

@ -52,9 +52,6 @@
#endif #endif
static const float kBorderResizeLength = 22.0;
static inline uint8 static inline uint8
blend_color_value(uint8 a, uint8 b, float position) blend_color_value(uint8 a, uint8 b, float position)
{ {
@ -209,6 +206,9 @@ DefaultDecorator::_DrawFrame(BRect rect)
if (fBorderWidth <= 0) if (fBorderWidth <= 0)
return; 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 // Draw the border frame
BRect border = BRect(fTopBorder.LeftTop(), fBottomBorder.RightBottom()); BRect border = BRect(fTopBorder.LeftTop(), fBottomBorder.RightBottom());
switch ((int)fTopTab->look) { switch ((int)fTopTab->look) {
@ -221,31 +221,36 @@ DefaultDecorator::_DrawFrame(BRect rect)
ComponentColors colors; ComponentColors colors;
_GetComponentColors(COMPONENT_TOP_BORDER, colors, fTopTab); _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( fDrawingEngine->StrokeLine(
BPoint(border.left + i, border.top + i), 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()) { if (fTitleBarRect.IsValid()) {
// grey along the bottom of the tab // grey along the bottom of the tab
// (overwrites "white" from frame) // (overwrites "white" from frame)
const int overdraw = ceilf(fBorderWidth / 5.0f);
for (int i = 1; i <= overdraw; i++) {
fDrawingEngine->StrokeLine( fDrawingEngine->StrokeLine(
BPoint(fTitleBarRect.left + 2, BPoint(fTitleBarRect.left + 2, fTitleBarRect.bottom + i),
fTitleBarRect.bottom + 1), BPoint(fTitleBarRect.right - 2, fTitleBarRect.bottom + i),
BPoint(fTitleBarRect.right - 2,
fTitleBarRect.bottom + 1),
colors[2]); colors[2]);
} }
} }
}
// left // left
if (rect.Intersects(fLeftBorder.InsetByCopy(0, -fBorderWidth))) { if (rect.Intersects(fLeftBorder.InsetByCopy(0, -fBorderWidth))) {
ComponentColors colors; ComponentColors colors;
_GetComponentColors(COMPONENT_LEFT_BORDER, colors, fTopTab); _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( fDrawingEngine->StrokeLine(
BPoint(border.left + i, border.top + i), 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 // bottom
@ -253,11 +258,12 @@ DefaultDecorator::_DrawFrame(BRect rect)
ComponentColors colors; ComponentColors colors;
_GetComponentColors(COMPONENT_BOTTOM_BORDER, colors, fTopTab); _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( fDrawingEngine->StrokeLine(
BPoint(border.left + i, border.bottom - i), BPoint(border.left + i, border.bottom - i),
BPoint(border.right - 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 // right
@ -265,11 +271,12 @@ DefaultDecorator::_DrawFrame(BRect rect)
ComponentColors colors; ComponentColors colors;
_GetComponentColors(COMPONENT_RIGHT_BORDER, colors, fTopTab); _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( fDrawingEngine->StrokeLine(
BPoint(border.right - i, border.top + i), BPoint(border.right - i, border.top + i),
BPoint(border.right - 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)]);
} }
} }
break; break;
@ -283,20 +290,23 @@ DefaultDecorator::_DrawFrame(BRect rect)
ComponentColors colors; ComponentColors colors;
_GetComponentColors(COMPONENT_TOP_BORDER, colors, fTopTab); _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( fDrawingEngine->StrokeLine(
BPoint(border.left + i, border.top + i), BPoint(border.left + i, border.top + i),
BPoint(border.right - i, border.top + i), BPoint(border.right - i, border.top + i),
colors[i * 2]); colors[colorsIndex * 2]);
} }
if (fTitleBarRect.IsValid() && fTopTab->look != kLeftTitledWindowLook) { if (fTitleBarRect.IsValid() && fTopTab->look != kLeftTitledWindowLook) {
// grey along the bottom of the tab // grey along the bottom of the tab
// (overwrites "white" from frame) // (overwrites "white" from frame)
const int overdraw = ceilf(fBorderWidth / 5.0f);
for (int i = 1; i <= overdraw; i++) {
fDrawingEngine->StrokeLine( fDrawingEngine->StrokeLine(
BPoint(fTitleBarRect.left + 2, BPoint(fTitleBarRect.left + 2, fTitleBarRect.bottom + i),
fTitleBarRect.bottom + 1), BPoint(fTitleBarRect.right - 2, fTitleBarRect.bottom + i),
BPoint(fTitleBarRect.right - 2, colors[2]);
fTitleBarRect.bottom + 1), colors[2]); }
} }
} }
// left // left
@ -304,11 +314,12 @@ DefaultDecorator::_DrawFrame(BRect rect)
ComponentColors colors; ComponentColors colors;
_GetComponentColors(COMPONENT_LEFT_BORDER, colors, fTopTab); _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( fDrawingEngine->StrokeLine(
BPoint(border.left + i, border.top + i), BPoint(border.left + i, border.top + i),
BPoint(border.left + i, border.bottom - i), BPoint(border.left + i, border.bottom - i),
colors[i * 2]); colors[colorsIndex * 2]);
} }
if (fTopTab->look == kLeftTitledWindowLook if (fTopTab->look == kLeftTitledWindowLook
&& fTitleBarRect.IsValid()) { && fTitleBarRect.IsValid()) {
@ -326,11 +337,12 @@ DefaultDecorator::_DrawFrame(BRect rect)
ComponentColors colors; ComponentColors colors;
_GetComponentColors(COMPONENT_BOTTOM_BORDER, colors, fTopTab); _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( fDrawingEngine->StrokeLine(
BPoint(border.left + i, border.bottom - i), BPoint(border.left + i, border.bottom - i),
BPoint(border.right - 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 // right
@ -338,11 +350,12 @@ DefaultDecorator::_DrawFrame(BRect rect)
ComponentColors colors; ComponentColors colors;
_GetComponentColors(COMPONENT_RIGHT_BORDER, colors, fTopTab); _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( fDrawingEngine->StrokeLine(
BPoint(border.right - i, border.top + i), BPoint(border.right - i, border.top + i),
BPoint(border.right - 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]);
} }
} }
break; break;
@ -393,22 +406,22 @@ DefaultDecorator::_DrawFrame(BRect rect)
case kLeftTitledWindowLook: case kLeftTitledWindowLook:
{ {
if (!rect.Intersects(BRect( if (!rect.Intersects(BRect(
fRightBorder.right - kBorderResizeLength, fRightBorder.right - fBorderResizeLength,
fBottomBorder.bottom - kBorderResizeLength, fBottomBorder.bottom - fBorderResizeLength,
fRightBorder.right - 1, fRightBorder.right - 1,
fBottomBorder.bottom - 1))) fBottomBorder.bottom - 1)))
break; break;
fDrawingEngine->StrokeLine( fDrawingEngine->StrokeLine(
BPoint(fRightBorder.left, BPoint(fRightBorder.left,
fBottomBorder.bottom - kBorderResizeLength), fBottomBorder.bottom - fBorderResizeLength),
BPoint(fRightBorder.right - 1, BPoint(fRightBorder.right - 1,
fBottomBorder.bottom - kBorderResizeLength), fBottomBorder.bottom - fBorderResizeLength),
colors[0]); colors[0]);
fDrawingEngine->StrokeLine( fDrawingEngine->StrokeLine(
BPoint(fRightBorder.right - kBorderResizeLength, BPoint(fRightBorder.right - fBorderResizeLength,
fBottomBorder.top), fBottomBorder.top),
BPoint(fRightBorder.right - kBorderResizeLength, BPoint(fRightBorder.right - fBorderResizeLength,
fBottomBorder.bottom - 1), fBottomBorder.bottom - 1),
colors[0]); colors[0]);
break; break;
@ -437,14 +450,15 @@ DefaultDecorator::_DrawResizeKnob(BRect rect, bool full,
fDrawingEngine->FillRect(rect, gradient); fDrawingEngine->FillRect(rect, gradient);
fDrawingEngine->StrokeLine(BPoint(x - 15, y - 15), BPoint offset1(15, 15), offset2(14, 14);
BPoint(x - 15, y - 2), colors[0]); fDrawingEngine->StrokeLine(BPoint(x, y) - offset1,
fDrawingEngine->StrokeLine(BPoint(x - 14, y - 14), BPoint(x - offset1.x, y - 2), colors[0]);
BPoint(x - 14, y - 1), colors[1]); fDrawingEngine->StrokeLine(BPoint(x, y) - offset2,
fDrawingEngine->StrokeLine(BPoint(x - 15, y - 15), BPoint(x - offset2.x, y - 1), colors[1]);
BPoint(x - 2, y - 15), colors[0]); fDrawingEngine->StrokeLine(BPoint(x, y) - offset1,
fDrawingEngine->StrokeLine(BPoint(x - 14, y - 14), BPoint(x - 2, y - offset1.y), colors[0]);
BPoint(x - 1, y - 14), colors[1]); fDrawingEngine->StrokeLine(BPoint(x, y) - offset2,
BPoint(x - 1, y - offset2.y), colors[1]);
if (!full) if (!full)
return; return;

View File

@ -163,8 +163,8 @@ TabDecorator::RegionAt(BPoint where, int32& tab) const
|| fTopTab->look == B_FLOATING_WINDOW_LOOK || fTopTab->look == B_FLOATING_WINDOW_LOOK
|| fTopTab->look == B_MODAL_WINDOW_LOOK || fTopTab->look == B_MODAL_WINDOW_LOOK
|| fTopTab->look == kLeftTitledWindowLook)) { || fTopTab->look == kLeftTitledWindowLook)) {
BRect resizeRect(BPoint(fBottomBorder.right - kBorderResizeLength, BRect resizeRect(BPoint(fBottomBorder.right - fBorderResizeLength,
fBottomBorder.bottom - kBorderResizeLength), fBottomBorder.bottom - fBorderResizeLength),
fBottomBorder.RightBottom()); fBottomBorder.RightBottom());
if (resizeRect.Contains(where)) if (resizeRect.Contains(where))
return REGION_RIGHT_BOTTOM_CORNER; return REGION_RIGHT_BOTTOM_CORNER;
@ -235,6 +235,9 @@ TabDecorator::_DoLayout()
bool hasTab = false; 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) { switch ((int)fTopTab->look) {
case B_MODAL_WINDOW_LOOK: case B_MODAL_WINDOW_LOOK:
fBorderWidth = 5; fBorderWidth = 5;
@ -259,6 +262,10 @@ TabDecorator::_DoLayout()
fBorderWidth = 0; fBorderWidth = 0;
} }
fBorderWidth *= scaleFactor;
fResizeKnobSize = kResizeKnobSize * scaleFactor;
fBorderResizeLength = kBorderResizeLength * scaleFactor;
// calculate left/top/right/bottom borders // calculate left/top/right/bottom borders
if (fBorderWidth > 0) { if (fBorderWidth > 0) {
// NOTE: no overlapping, the left and right border rects // NOTE: no overlapping, the left and right border rects
@ -286,8 +293,8 @@ TabDecorator::_DoLayout()
// calculate resize rect // calculate resize rect
if (fBorderWidth > 1) { if (fBorderWidth > 1) {
fResizeRect.Set(fBottomBorder.right - kResizeKnobSize, fResizeRect.Set(fBottomBorder.right - fResizeKnobSize,
fBottomBorder.bottom - kResizeKnobSize, fBottomBorder.right, fBottomBorder.bottom - fResizeKnobSize, fBottomBorder.right,
fBottomBorder.bottom); fBottomBorder.bottom);
} else { } else {
// no border or one pixel border (menus and such) // no border or one pixel border (menus and such)
@ -360,15 +367,16 @@ TabDecorator::_DoTabLayout()
fDrawState.Font().GetHeight(fontHeight); fDrawState.Font().GetHeight(fontHeight);
if (tab->look != kLeftTitledWindowLook) { if (tab->look != kLeftTitledWindowLook) {
const float spacing = fBorderWidth * 1.4f;
tabRect.Set(fFrame.left - fBorderWidth, tabRect.Set(fFrame.left - fBorderWidth,
fFrame.top - fBorderWidth fFrame.top - fBorderWidth
- ceilf(fontHeight.ascent + fontHeight.descent + 7.0), - ceilf(fontHeight.ascent + fontHeight.descent + spacing),
((fFrame.right - fFrame.left) < 35.0 ? ((fFrame.right - fFrame.left) < (spacing * 5) ?
fFrame.left + 35.0 : fFrame.right) + fBorderWidth, fFrame.left + (spacing * 5) : fFrame.right) + fBorderWidth,
fFrame.top - fBorderWidth); fFrame.top - fBorderWidth);
} else { } else {
tabRect.Set(fFrame.left - fBorderWidth 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.top - fBorderWidth, fFrame.left - fBorderWidth,
fFrame.bottom + fBorderWidth); fFrame.bottom + fBorderWidth);
} }
@ -608,9 +616,9 @@ TabDecorator::_ResizeBy(BPoint offset, BRegion* dirty)
case B_MODAL_WINDOW_LOOK: case B_MODAL_WINDOW_LOOK:
case kLeftTitledWindowLook: case kLeftTitledWindowLook:
// The bottom border resize line // The bottom border resize line
realResizeRect.Set(fRightBorder.right - kBorderResizeLength, realResizeRect.Set(fRightBorder.right - fBorderResizeLength,
fBottomBorder.top, fBottomBorder.top,
fRightBorder.right - kBorderResizeLength, fRightBorder.right - fBorderResizeLength,
fBottomBorder.bottom - 1); fBottomBorder.bottom - 1);
// Old location // Old location
dirty->Include(realResizeRect); dirty->Include(realResizeRect);
@ -620,9 +628,9 @@ TabDecorator::_ResizeBy(BPoint offset, BRegion* dirty)
// The right border resize line // The right border resize line
realResizeRect.Set(fRightBorder.left, realResizeRect.Set(fRightBorder.left,
fBottomBorder.bottom - kBorderResizeLength, fBottomBorder.bottom - fBorderResizeLength,
fRightBorder.right - 1, fRightBorder.right - 1,
fBottomBorder.bottom - kBorderResizeLength); fBottomBorder.bottom - fBorderResizeLength);
// Old location // Old location
dirty->Include(realResizeRect); dirty->Include(realResizeRect);
realResizeRect.OffsetBy(offset); realResizeRect.OffsetBy(offset);
@ -916,7 +924,7 @@ TabDecorator::_GetFootprint(BRegion *region)
if (fTopTab->look == B_DOCUMENT_WINDOW_LOOK) { if (fTopTab->look == B_DOCUMENT_WINDOW_LOOK) {
// include the rectangular resize knob on the bottom right // 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, region->Include(BRect(fFrame.right - knobSize, fFrame.bottom - knobSize,
fFrame.right, fFrame.bottom)); fFrame.right, fFrame.bottom));
} }
@ -1058,8 +1066,10 @@ TabDecorator::_LayoutTabItems(Decorator::Tab* _tab, const BRect& tabRect)
float float
TabDecorator::_DefaultTextOffset() const TabDecorator::_DefaultTextOffset() const
{ {
return (fTopTab->look == B_FLOATING_WINDOW_LOOK if (fTopTab->look == B_FLOATING_WINDOW_LOOK
|| fTopTab->look == kLeftTitledWindowLook) ? 10 : 18; || fTopTab->look == kLeftTitledWindowLook)
return int32(fBorderWidth * 3.4f);
return int32(fBorderWidth * 3.6f);
} }

View File

@ -137,6 +137,7 @@ protected:
protected: protected:
BRegion fTabsRegion; BRegion fTabsRegion;
BRect fOldMovingTab; BRect fOldMovingTab;
float fBorderResizeLength, fResizeKnobSize;
rgb_color fFocusFrameColor; rgb_color fFocusFrameColor;