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
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,31 +221,36 @@ 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)
const int overdraw = ceilf(fBorderWidth / 5.0f);
for (int i = 1; i <= overdraw; i++) {
fDrawingEngine->StrokeLine(
BPoint(fTitleBarRect.left + 2,
fTitleBarRect.bottom + 1),
BPoint(fTitleBarRect.right - 2,
fTitleBarRect.bottom + 1),
BPoint(fTitleBarRect.left + 2, fTitleBarRect.bottom + i),
BPoint(fTitleBarRect.right - 2, fTitleBarRect.bottom + i),
colors[2]);
}
}
}
// left
if (rect.Intersects(fLeftBorder.InsetByCopy(0, -fBorderWidth))) {
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)
const int overdraw = ceilf(fBorderWidth / 5.0f);
for (int i = 1; i <= overdraw; i++) {
fDrawingEngine->StrokeLine(
BPoint(fTitleBarRect.left + 2,
fTitleBarRect.bottom + 1),
BPoint(fTitleBarRect.right - 2,
fTitleBarRect.bottom + 1), colors[2]);
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;

View File

@ -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);
}

View File

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